#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer.h"
#include "IGraphicsEngineRenderer.hpp"
#include "GameObject.hpp"
#include "TransformComponent.hpp"

#include <vector>

#if defined(LINUX) || defined(MINGW)
#include <SDL2/SDL.h>
#else
#include <SDL.h>
#endif

/**
 * The GUI creating the game editor.
 * Displays menus allowing for creation, editing, and destruction of all {@link GameObject GameObjects} and {@link Component Components}
 */
class GameMakerGUI {
public:
    /**
     * Construct a new Game Maker GUI object
     * 
     * @param window the window to be drawn to
     * @param renderer the renderer to be drawn to
     * @param gameObjects all game objects in the game
     * @see Engine#InitializeGUI()
     * @see Engine#Render()
     */
    GameMakerGUI(SDL_Window* window, SDL_Renderer* renderer, std::vector<GameObject*>* gameObjects);

    /**
     * Destroy the Game Maker GUI object
     */
    ~GameMakerGUI();

    /**
     * Forwards all input on to ImGui
     */
    void Input(SDL_Event e);

    /**
     * The main function to draw the GUI.
     * Dispatches member functions to draw various editor menus.
     * 
     * @param mRenderer the renderer to be drawn to
     * @param runGame pointer to the bool controlling @link Engine#MainGameLoop() @endlink
     */
    void RenderEditor(IGraphicsEngineRenderer* mRenderer, bool* runGame);

private:
    /**
     * Pointers to all the game objects in the Engine.
     */
    std::vector<GameObject *>* m_gameobjects;

    /**
     * Displays a window containing all GameObjects.
     * @see #CreateNewGameObject()
     * @see #EditGameObject()
     */
    void ShowGameObjectWindow();

    /**
     * Displays internal GUI static variables for debugging purposes.
     */
    void ShowDebugWindow();

    /**
     * Displays a window to create a new @link GameObject @endlink.
     */
    void CreateNewGameObject();

    /**
     * Displays a window to edit a @link GameObject @endlink.
     * @see #CreateComponent()
     */
    void EditGameObject();

    /**
     * Displays a window to create a new @link Component @endlink
     * 
     * @param ren the renderer a new component might need
     */
    void CreateComponent(IGraphicsEngineRenderer* ren);

    /**
     * Gets a TransformComponent attached to the given GameObject
     * 
     * @param curObj the game object being checked
     * @return a TransformComponent attached to curObj
     */
    TransformComponent* FindTransform(GameObject*curObj);
};