#ifndef _GAME_GUI_H
#define _GAME_GUI_H

#include <string>
#include <vector>

#ifdef GAMEGUI_INCLUDE_VULKAN
   #include <vulkan/vulkan.h>
#endif

// These are included here so I can implement the RawEvent union, which requires knowledge
// of the ui event types of all ui libraries I might use for any of the GameGui clases
// GLFW does not have its own event type though, so SDL is currently the only library this is done for
#include <SDL2/SDL.h>

using namespace std;

// TODO: See if it makes sense to combine this with the files in the gui folder

enum EventType {
   UI_EVENT_QUIT,
   UI_EVENT_WINDOW,
   UI_EVENT_WINDOWRESIZE,
   UI_EVENT_KEYDOWN,
   UI_EVENT_KEYUP,
   UI_EVENT_MOUSEBUTTONDOWN,
   UI_EVENT_MOUSEBUTTONUP,
   UI_EVENT_MOUSEMOTION,
   UI_EVENT_UNHANDLED,
   UI_EVENT_UNKNOWN
};

union RawEvent {
   SDL_Event sdl;
};

struct KeyEvent {
   EventType type;
   unsigned int keycode;
   bool repeat;
};

struct MouseEvent {
   EventType type;
   int x;
   int y;
   /*
      int button;
      int action;
   */
};

struct WindowEvent {
   EventType type;
};

struct WindowResizeEvent {
   EventType type;
   int width;
   int height;
};

// TODO: Switch from union to std::variant

union GameEvent {
   EventType type;
   WindowEvent window;
   KeyEvent key;
   MouseEvent mouse;
   WindowResizeEvent windowResize;
};

struct UIEvent {
   RawEvent rawEvent;
   GameEvent event;
};

class GameGui {
   public:
      virtual ~GameGui() {};

      virtual string& getError() = 0;

      virtual bool init() = 0;
      virtual void shutdown() = 0;

      virtual void* createWindow(const string& title, int width, int height, bool fullscreen) = 0;
      virtual void destroyWindow() = 0;

      virtual void processEvents() = 0;
      virtual int pollEvent(UIEvent* uiEvent) = 0;
      virtual bool keyPressed(unsigned int key) = 0;

      virtual void refreshWindowSize() = 0;
      virtual int getWindowWidth() = 0;
      virtual int getWindowHeight() = 0;

#ifdef GAMEGUI_INCLUDE_VULKAN
      virtual bool createVulkanSurface(VkInstance instance, VkSurfaceKHR* surface) = 0;
      virtual vector<const char*> getRequiredExtensions() = 0;
#endif
};

#endif // _GAME_GUI_H
