#include "DeerRender/Application.h"
#include <functional>
#include <thread>

#include "DeerRender/Render/Render.h"
#include "DeerRender/Render/RenderCommand.h"
#include "DeerRender/Render/RenderUtils.h"

#include "DeerRender/Log.h"

#include "DeerRender/ImGui/ImGuiLayer.h"
#include "imgui.h"

namespace Deer {
	namespace Application {
		Function renderCallback;
		EventFunction eventCallback;
		Scope<Window> window;
		Scope<ImGuiLayer> imGuiLayer;

		void setRenderCallback(Function _render) {
			renderCallback = _render;
		}

		void setEventCallback(EventFunction _event) {
			eventCallback = _event;
		}

		Window& getWindow() {
			return *window;
		}

		void internalEventCallback(Event& e) {
			if (eventCallback)
				eventCallback(e);

			imGuiLayer->onEvent(e);
		}

		void initWindow() {
			window = Scope<Window>(Window::create());

			window->setEventCallback(Deer::Application::internalEventCallback);
			window->initWindow();

			imGuiLayer = MakeScope<ImGuiLayer>();
			imGuiLayer->onAttach();

			RenderUtils::initializeRenderUtils();
			RenderCommand::init();
		}

		void resolveEvents() {
			window->resolveEvents();
		}

		void shutdownWindow() {
			imGuiLayer->onDetach();

			imGuiLayer.reset();
			window.reset();
		}

		void runRender(float deltaTime) {
			if (!renderCallback)
				return;

			RenderCommand::setClearColor({0.2f, 0.2f, 0.3f, 1.0f});
			RenderCommand::clear();

			ImGuiIO& io = ImGui::GetIO();
			io.DeltaTime = (float)deltaTime;
			imGuiLayer->begin();

			renderCallback();

			imGuiLayer->end();
			window->onRender();
		}

	} // namespace Application
} // namespace Deer