#include "DeerStudio.h"

#include <functional>

#include "Deer/DataStore.h"
#include "Deer/Scene.h"
#include "Deer/ScriptEngine.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include "DeerRender/Mesh.h"
#include "DeerStudio/EditorEngine.h"

#include "DeerStudio/Fonts.h"
#include "DeerStudio/Editor/GamePanel.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/Terrain/TerrainEditor.h"
#include "DeerStudio/Editor/Viewport.h"
#include "Style.h"

void extract_angelScript();

namespace Deer {
	int DeerStudioApplication::onPreInit() {
		Path projectPath = Application::m_window->folderDialog(nullptr);
		if (projectPath.empty()) return 1;

		DataStore::rootPath = projectPath;
		DataStore::loadVoxelsData();
		DataStore::loadVoxelsAspect();
		return 0;
	}

	int DeerStudioApplication::onInit() {
		DataStore::generateTextureAtlas();
		DataStore::loadVoxelsShaders();
		
		EditorEngine::initialize();

		Icons::setupIcons();

		// IMGUI STYLE
		ImGuiIO& io = ImGui::GetIO();

		std::string fLoc = (DataStore::rootPath / "imgui.ini").generic_string();
		char* filenameFLoc = new char[fLoc.size() + 1]();
		strcpy(filenameFLoc, fLoc.c_str());
		io.IniFilename = filenameFLoc;

		initializeFonts();

		SetupImGuiStyle();

		ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 20));
		auto m_gamePanel = Ref<GamePanel>(new GamePanel());
		Panels.push_back(m_gamePanel);

		return 0;
	}

	void DeerStudioApplication::onShutdown() {
		if (Scene::getExecutingState())
			Scene::endExecution();

		Panels.clear();
		EditorEngine::deinitialize();
	}

	void DeerStudioApplication::onRender(Timestep delta) {
		for (auto Panel : Panels) {
			Panel->onRender(delta);
		}

		int windowWidth = Application::s_application->m_window->getWitdth();
		int windowHeight = Application::s_application->m_window->getHeight();
	}

	void DeerStudioApplication::onUpdate(Timestep delta) {
		if (Scene::getExecutingState())
			Scene::tickExecution();
		
		if (VoxelWorld::isInitialized())
			VoxelWorld::bakeNextChunk();		
	}

	void DeerStudioApplication::onEvent(Event& e) {
		for (auto& Panel : Panels) Panel->onEventCallback(e);

		viewport_onEvent(e);
	}

	void DeerStudioApplication::onImGUI() {
		static bool opt_fullscreen = true;
		static bool opt_padding = false;
		static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;

		ImGuiWindowFlags window_flags =
		    ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;

		{
			const ImGuiViewport* viewport = ImGui::GetMainViewport();
			ImGui::SetNextWindowPos(viewport->WorkPos);
			ImGui::SetNextWindowSize(viewport->WorkSize);
			ImGui::SetNextWindowViewport(viewport->ID);
			window_flags |= ImGuiWindowFlags_NoTitleBar |
			                ImGuiWindowFlags_NoCollapse |
			                ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
			window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus |
			                ImGuiWindowFlags_NoNavFocus;
			window_flags |= ImGuiWindowFlags_NoBackground;
		}

		static bool p_open = true;
		ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
		ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
		ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
		ImGui::Begin("DockSpace Demo", &p_open, window_flags);
		ImGui::PopStyleVar();
		ImGui::PopStyleVar(2);

		ImGuiID dockspace_id = ImGui::GetID("DockSpace Demo");
		ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);

		if (ImGui::BeginMenuBar()) {
			drawMenuBar();
			ImGui::EndMenuBar();
		}

		for (auto Panel : Panels) {
			Panel->onImGui();
		}

		// ---- PanelS -----
		TerrainEditor::onImGui();
		viewport_onImGui();
		EditorEngine::render();
		// ---- PanelS -----
		Scene::gizmoRenderer.refresh();
		ImGui::End();
	}

	void DeerStudioApplication::drawMenuBar() {
		if (ImGui::BeginMenu("Project")) {
			if (ImGui::MenuItem("New project")) {
			}
			if (ImGui::MenuItem("Open project")) {
			}
			if (ImGui::MenuItem("Save project")) {
			}
			if (ImGui::MenuItem("Save project as...")) {
			}
			ImGui::Separator();
			if (ImGui::MenuItem("Create binaries")) {
			}
			if (ImGui::MenuItem("Export project")) {
			}
			if (ImGui::MenuItem("Project settings")) {
			}
			ImGui::EndMenu();
		}

		if (ImGui::BeginMenu("Scene")) {
			if (ImGui::MenuItem("New scene")) {
				// TODO
				Scene::clear();
				DataStore::exportScene("new_scene");
			}
			// if (Project::m_sceneSerializer->getCurrentScenePath() !=
			// "_NO_INITIALIZED_" && ImGui::MenuItem("Save scene")) {
			//     Project::m_sceneSerializer->serialize(Project::m_sceneSerializer->getCurrentScenePath());
			// }
			if (ImGui::MenuItem("Save scene")) {
				DataStore::exportScene("saved_scene");
			}
			if (ImGui::MenuItem("Save scene as...")) {
				// TODO
			}
			if (ImGui::MenuItem("Load scene")) {
				// Scene::swap(DataStore::loadScene("new_scene"));
				// DataStore::exportScene(Project::m_scene,
				// "new_scene");
			}
			if (ImGui::MenuItem("Scene settings")) {
				// TODO
			}
			ImGui::EndMenu();
		}

		if (ImGui::BeginMenu("Runtime")) {
			if (ImGui::MenuItem("Start")) {
				// TODO
			}
			if (ImGui::MenuItem("End")) {
				// TODO
			}
			if (ImGui::MenuItem("Restart")) {
				// TODO
			}
			ImGui::EndMenu();
		}

		if (ImGui::BeginMenu("Voxel")) {
			if (ImGui::MenuItem("Voxel Panel")) {
				// TODO
			}

			ImGui::EndMenu();
		}

		if (ImGui::BeginMenu("Interface")) {
			if (ImGui::MenuItem("Reload interface")) {
				EditorEngine::initialize();
			}
			ImGui::EndMenu();
		}

		if (ImGui::BeginMenu("Scripts")) {
			if (ImGui::MenuItem("Reload scripts") &&
			    !Scene::getExecutingState()) {
			}

			ImGui::EndMenu();
		}

		if (ImGui::BeginMenu("Help")) {
			if (ImGui::MenuItem("Documentation")) {
				// TODO
			}
			if (ImGui::MenuItem("Report bug")) {
				// TODO
			}
			if (ImGui::MenuItem("About")) {
				// TODO
			}
			ImGui::EndMenu();
		}
	}

	void DeerStudioApplication::onChangeScene() { ActiveEntity::clear(); }
}  // namespace Deer