#pragma once
#include "olcPixelGameEngine.h"
#include <stack>
#include "safemap.h"
#include "Theme.h"
#include "Attributable.h"
#include "olcUTIL_Geometry2D.h"
#include <functional>

class Crawler;
class MenuComponent;

enum MenuType{
    TEST,
    TEST_2,
    INVENTORY,

    ///////////////////////////////////////////////////////////
    /*DO NOT REMOVE!!*/ENUM_END////////////////////////////////
    ///////////////////////////////////////////////////////////
};

class Menu:IAttributable{
    friend class Crawler;
    friend class Player;
    static bool MOUSE_NAVIGATION;

    float buttonHoldTime=0;
    std::map<int/*Y*/,std::vector<MenuComponent*>>buttons; //Buttons are stored in rows followed by their column order.
    std::map<int/*Y*/,std::vector<MenuComponent*>>newButtonArrangement; //The new setup that the buttons will be at if a drag operation completes.
    std::vector<MenuComponent*>displayComponents; //Components that are only for displaying purposes.
    vi2d selection={-1,-1};

    MenuComponent*draggingComponent=nullptr;
    Renderable r,overlay;
public:
    Menu();
    Menu(vf2d pos,vf2d size);
    void AddComponent(std::string key,MenuComponent*button);
    void Update(Crawler*game);
    void Draw(Crawler*game);
    static void InitializeMenus();
    static void OpenMenu(MenuType menu);
    static std::vector<Menu*>stack;
    static std::string themeSelection;
    static safeunorderedmap<std::string,Theme>themes;
    static const vf2d CENTERED;
    safemap<std::string,MenuComponent*>components; //A friendly way to interrogate any component we are interested in.
    static std::map<MenuType,Menu*>menus;
    vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
    vf2d size; //Size in tiles (24x24), every menu will be tile-based

private:
    void HoverMenuSelect(Crawler*game);
    void MenuSelect(Crawler*game);
    void CheckClickAndPerformMenuSelect(Crawler*game);
    static Menu*InitializeTestMenu();
    static Menu*InitializeTestSubMenu();
    static Menu*InitializeInventoryWindow();
    //X (0-3), Y (0-2) for specific 9-patch tile (tiled version).
    static Renderable&GetPatchPart(int x,int y);

    static Theme&GetCurrentTheme();

    void KeyboardButtonNavigation(Crawler*game,vf2d menuPos);
    void DrawScaledWindowBackground(Crawler*game,vf2d menuPos);
    void DrawTiledWindowBackground(Crawler*game,vf2d menuPos);
    void DrawScaledWindowBorder(Crawler*game,vf2d menuPos);
    void DrawTiledWindowBorder(Crawler*game,vf2d menuPos);

    Pixel GetRenderColor();
};

struct MenuFuncData{
    Menu&menu;
    Crawler*game;
    MenuComponent*component;
};

typedef std::function<void(MenuFuncData)> MenuFunc;