#include "wrap-string.hpp"
#include "wrap-map.hpp"
#include "wrap-vector.hpp"

#include "gui.hpp"
#include "luastack.hpp"

void Gui::store_global_pointer(lua_State *L, Gui *g) {
    lua_pushstring(L, "gui");
    lua_pushlightuserdata(L, g);
    lua_rawset(L, LUA_REGISTRYINDEX);
}

Gui *Gui::fetch_global_pointer(lua_State *L) {
    lua_pushstring(L, "gui");
    lua_rawget(L, LUA_REGISTRYINDEX);
    Gui *result = (Gui *)lua_touserdata(L, -1);
    if (result == nullptr) {
        luaL_error(L, "Not currently building a GUI");
    }
    lua_pop(L, 1);
    return result;
}

void Gui::menu_item(const eng::string &action, const eng::string &label) {
    GuiElt elt;
    elt.type_ = GuiElt::TYPE_MENU_ITEM;
    elt.action_ = action;
    elt.label_ = label;
    elts_.push_back(elt);
}

bool Gui::has_action(const eng::string &action) const {
    for (const GuiElt &elt : elts_) {
        if (elt.action_ == action) {
            return true;
        }
    }
    return false;
}

eng::string Gui::get_action(int index) {
    if ((index < 0) || (index >= int(elts_.size()))) {
        return "";
    }
    return elts_[index].action();
}

eng::string Gui::menu_debug_string() const {
    eng::ostringstream oss;
    int index = 0;
    for (const GuiElt &elt : elts()) {
        oss << index << " " << elt.label() << std::endl;
        index += 1;
    }
    return oss.str();
}

LuaDefine(gui_menu_item, "action,label", "add a menu item to the current gui") {
    Gui *gui = Gui::fetch_global_pointer(L);
    LuaArg laction, llabel;
    LuaStack LS(L, laction, llabel);
    eng::string action = LS.ckstring(laction);
    eng::string label = LS.ckstring(llabel);
    if (!util::has_prefix(action, "cb_")) {
        luaL_error(L, "menuitem callbacks must start with cb_");
    }
    gui->menu_item(action, label);
    return LS.result();
}
