#include "ui_menu.h"
#include "ui.h"
#include <vector>
#include <string>

namespace ui
{
    namespace menu
    {
        #define OPTION_TYPE_NORMAL      0
        #define OPTION_TYPE_SEPARATOR   1
        #define OPTION_TYPE_BOOLEAN     2

        struct option_t
        {
            std::string label;
            int type;
            int value;
            int (*callback)(int);
        };

        struct menu_t
        {
            std::string label;
            SDL_Rect rect;
            std::vector<option_t> options;
        };

        void(*exit_callback)(void) = nullptr;
        std::vector<menu_t> menus;
        int visible_menu = -1;
        int menu_x = 0;

        void init()
        {
            // No se si hi ha algo que fer ací...
        }

        void show()
        {
            int mx, my;
            Uint32 mb = SDL_GetMouseState(&mx, &my);
            mx=mx/CHR_W; my=my/CHR_H;
            int w;
            ui::printrect(0, 0, 320, 1, COLOR_BLACK);
            int opt_pos=1;
            int index=0;
            for (auto &menu : menus)
            {
                const int text_size = (menu.label.size()+2);
                uint8_t text_color = COLOR_WHITE;
                if (my<1 && mx>=opt_pos && mx<opt_pos+text_size)
                {
                    ui::printrect(opt_pos-1, 0, text_size, 1, COLOR_DARK_BLUE);
                    text_color = COLOR_WHITE;
                    visible_menu = index;
                    menu_x = opt_pos-1;
                }
                ui::printtxt(opt_pos, 0, menu.label.c_str(), text_color);
                opt_pos+=text_size;
                index++;
            }
            if (visible_menu!=-1)
            {
                opt_pos=2;
                menu_t &m = menus[visible_menu];
                ui::printrect(menu_x, 1, 22, m.options.size()+2, COLOR_BLACK);
                ui::box(menu_x, 1, 22, m.options.size()+2, COLOR_WHITE);
                for (auto &option : m.options)
                {
                    if (option.type!=OPTION_TYPE_SEPARATOR)
                    {
                        const int text_size = (option.label.size()+2);
                        uint8_t text_color = COLOR_WHITE;
                        if (my==opt_pos && mx>=menu_x && mx<menu_x+text_size)
                        {
                            ui::printrect(menu_x+1, opt_pos, 20, 1, COLOR_DARK_BLUE);
                            text_color = COLOR_WHITE;
                            if (ui::getClicked())
                            {
                                if (option.callback) option.value = option.callback(option.value);
                                if (exit_callback) exit_callback();
                                return;
                            }
                        }
                        ui::printtxt(menu_x+1, opt_pos, option.label.c_str(), text_color);

                        if (option.type==OPTION_TYPE_BOOLEAN)
                        {
                            const char *check = option.value?"[X]":"[ ]";
                            ui::printtxt(menu_x+18, opt_pos, check, text_color);
                        }
                    }
                    opt_pos++;
                }
            }
        }

        void setexitcallback(void(*callback)(void))
        {
            exit_callback = callback;
        }

        const int addsubmenu(const char *label)
        {
            menu_t m;
            m.label = label;
            m.rect = {0, 0, 100, 0};
            menus.push_back(m);

            return menus.size()-1;
        }

        void addoption(int menu, const char *label, int(*callback)(int))
        {
            option_t op;
            op.type = OPTION_TYPE_NORMAL;
            op.label = label;
            op.callback = callback;
            menus[menu].options.push_back(op);
            menus[menu].rect.h += 15;
        }

        void addbooloption(int menu, const char *label, bool default_value, int(*callback)(int))
        {
            option_t op;
            op.type = OPTION_TYPE_BOOLEAN;
            op.label = label;
            op.value = default_value?1:0;
            op.callback = callback;
            menus[menu].options.push_back(op);
            menus[menu].rect.h += 15;
        }

        void addseparator(int menu)
        {
            option_t op;
            op.type = OPTION_TYPE_SEPARATOR;
            menus[menu].options.push_back(op);
        }
    }
}