#include "SDL.hpp"

#ifdef _WIN32
#include "D3D.hpp"
#include <windows.h>
#include <imgui_impl_dx11.h>
#endif

#include <SDL.h>
#include <imgui_impl_sdl2.h>
#include <imgui.h>

#include <string>
#include <iostream>

namespace Li::Gui {
	SDL::SDL(std::string windowTitle, int windowWidth, int windowHeight) {
		if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
		{
			std::cerr << "Error: " << SDL_GetError() << std::endl;
			return;
		}

#ifdef SDL_HINT_IME_SHOW_UI
		SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
#endif
		SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
		this->window = SDL_CreateWindow(windowTitle.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, windowFlags);
		SDL_VERSION(&this->wmInfo.version);
		SDL_GetWindowWMInfo(this->window, &this->wmInfo);

#ifdef _WIN32
		HWND hwnd = (HWND)this->wmInfo.info.win.window;
		this->renderer = new D3D(hwnd);
#else
#error no renderer for this platform
#endif

		IMGUI_CHECKVERSION();
		ImGui::CreateContext();
		ImGuiIO& io = ImGui::GetIO();
		io.IniFilename = nullptr;
		io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
		io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
		ImGui::StyleColorsDark();

#ifdef _WIN32
		ImGui_ImplSDL2_InitForD3D(this->window);
		this->renderer->InitImgui();
#else
#error No imgui renderer backend provided for this platform
#endif
		isExiting = false;
	}
	bool SDL::IsExiting() {
		return this->isExiting;
	}
	void SDL::PollEvent() {
		SDL_Event event;
		while (SDL_PollEvent(&event))
		{
			ImGui_ImplSDL2_ProcessEvent(&event);
			if (event.type == SDL_QUIT)
				this->isExiting = true;
			if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
				this->isExiting = true;
			if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
			{
				// Release all outstanding references to the swap chain's buffers before resizing.
#ifdef _WIN32
				D3D* d3d = (D3D*)this->renderer;
				d3d->Resize();
#else
#error No resize method provided for this platform
#endif
			}
		}
	}
	void SDL::NewFrame() {
		this->renderer->ImGuiNewFrame();
		ImGui_ImplSDL2_NewFrame();
		ImGui::NewFrame();
	}
	

	void SDL::Render() {
		ImGui::Render();
		ImVec4 clearColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
		this->renderer->Render(clearColor);
	}

	SDL::~SDL() {
#ifdef _WIN32
		ImGui_ImplDX11_Shutdown();
#endif
		ImGui_ImplSDL2_Shutdown();
		ImGui::DestroyContext();

		delete renderer;
		SDL_DestroyWindow(this->window);
		SDL_Quit();
	}
}