#pragma once
#include <iostream>
#include <Windows.h>
#include <string>
#include <vector>
#include <functional>
#include <memory>
#include "Layer.hpp"
#include "imgui.hpp"
#include "imgui_impl_win32.hpp"
#include "imgui_impl_dx12.hpp"
#include "imgui_internal.hpp"
#include <d3d12.h>
#include <dxgi1_4.h>
#include <wingdi.h>
#include <chrono>
#include <thread>
#include "Fonts/Roboto-Bold.hpp"
#include "Fonts/InterFont.hpp"
#include "Fonts/Awesome.hpp"
#include "Fonts/Awesome_Light.hpp"
#include "Fonts/FontAwesome5/font_awesome_5.hpp"

namespace ImGui
{
	extern ImFont* Header;
	extern ImFont* Header2;
	extern ImFont* Body;
	extern ImFont* Body2;
	extern ImFont* FA;
	extern ImFont* FA2;
	extern ImFont* FA3;
	extern ImFont* Icon;
}

namespace Desktop
{
	static ImVec2 windowPos = { 0,0 };
	static ImVec2 screenSize = { 0, 0 };
	static ImVec2 windowSize = { 500, 200 };

	struct ApplicationSpecification
	{
		LPCWSTR Name = L"";
		ImVec2 Size = { 0,0 };
	};

	class Application
	{
	public:
		Application(const ApplicationSpecification& applicationSpecification = ApplicationSpecification());
		~Application();

		static Application& Get();

		void CalculateWindowPos();

		static ImVec2 GetWindowSize();

		static void SetWindowSize(ImVec2 const size);

		void Run();

		template<typename T>
		void PushLayer()
		{
			static_assert(std::is_base_of<Layer, T>::value, "Pushed type is not subclass of Layer!");
			m_LayerStack.emplace_back(std::make_shared<T>())->OnAttach();
		}

		void PushLayer(const std::shared_ptr<Layer>& layer) { m_LayerStack.emplace_back(layer); layer->OnAttach(); }

		void Close();

	private:
		void Init(LPCWSTR appName, ImVec2 appWindowSize);
		void Shutdown();
	private:
		ApplicationSpecification m_Specification;
		bool m_Running = false;

		std::vector<std::shared_ptr<Layer>> m_LayerStack;
		std::function<void()> m_MenubarCallback;
	};

	// Implemented by CLIENT
	Application* CreateApplication(int argc, char** argv);
}