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

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

#include "Deer/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->setEventCallback(eventCallback);
        }

        Window& getWindow() {
            return *window;
        }

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

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

            if (eventCallback)
                window->setEventCallback(eventCallback);

		    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();
        }

    }
}