#include "DeerStudio/EditorEngine/API/Layout.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "angelscript.h"
#include "imgui.h"
#include "scriptany.h"

namespace Deer {
	namespace EditorEngine {
		void treeNode(std::string& txt, bool active) {
			ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf |
			                           ImGuiTreeNodeFlags_NoTreePushOnOpen |
			                           ImGuiTreeNodeFlags_SpanFullWidth;

			if (active)
				flags |= ImGuiTreeNodeFlags_Selected;

			ImGui::TreeNodeEx(txt.c_str(), flags);
		}

		bool treeNodeRecursive(std::string& txt, bool active, CScriptAny* data,
		                       asIScriptFunction& func) {
			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
			ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnDoubleClick |
			                           ImGuiTreeNodeFlags_OpenOnArrow |
			                           ImGuiTreeNodeFlags_SpanFullWidth |
			                           ImGuiTreeNodeFlags_DefaultOpen;

			if (active)
				flags |= ImGuiTreeNodeFlags_Selected;

			if (ImGui::TreeNodeEx(txt.c_str(), flags)) {
				ImGui::PushID(txt.c_str());
				if (executingScriptContext &&
				    executingScriptContext->PushState() == asSUCCESS) {
					AS_CHECK_ADDITIONAL_INFO(
					    executingScriptContext->Prepare(&func),
					    func.GetDeclaration());

					AS_CHECK_ADDITIONAL_INFO(
					    executingScriptContext->SetArgObject(0, data),
					    func.GetDeclaration());

					AS_CHECK_ADDITIONAL_INFO(executingScriptContext->Execute(),
					                         func.GetDeclaration());

					executingScriptContext->PopState();
				} else {
					ImGui::Text("Something failed");
				}

				ImGui::PopID();
				ImGui::TreePop();

				ImGui::PopStyleVar();
				return true;
			}

			ImGui::PopStyleVar();
			return false;
		}

		bool componentNode(std::string& txt, CScriptAny* data,
		                   asIScriptFunction* func) {

			ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));

			ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_SpanAvailWidth |
			                           ImGuiTreeNodeFlags_Framed |
			                           ImGuiTreeNodeFlags_AllowItemOverlap |
			                           ImGuiTreeNodeFlags_FramePadding |
			                           ImGuiTreeNodeFlags_DefaultOpen;

			if (ImGui::TreeNodeEx(txt.c_str(), flags)) {
				ImGui::Dummy(ImVec2(0, 10));
				ImGui::PushID(txt.c_str());
				if (executingScriptContext &&
				    executingScriptContext->PushState() == asSUCCESS) {

					AS_CHECK(executingScriptContext->Prepare(func));

					AS_CHECK(executingScriptContext->SetArgObject(0, data));

					AS_CHECK(executingScriptContext->Execute());

					executingScriptContext->PopState();
				} else {
					ImGui::Text("Something failed");
				}

				ImGui::Dummy(ImVec2(0, 10));
				ImGui::PopID();
				ImGui::TreePop();

				ImGui::PopStyleVar(2);
				return true;
			}

			ImGui::PopStyleVar(2);
			return false;
		}

		bool componentNode_contextMenu(std::string& txt, CScriptAny* data,
		                               asIScriptFunction* func,
		                               asIScriptFunction* menu) {

			ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));

			ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_SpanAvailWidth |
			                           ImGuiTreeNodeFlags_Framed |
			                           ImGuiTreeNodeFlags_AllowItemOverlap |
			                           ImGuiTreeNodeFlags_FramePadding |
			                           ImGuiTreeNodeFlags_DefaultOpen;

			if (ImGui::TreeNodeEx(txt.c_str(), flags)) {
				ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,
				                    ImVec2(10, 10));
				if (ImGui::BeginPopupContextItem(txt.c_str())) {
					if (executingScriptContext &&
					    executingScriptContext->PushState() == asSUCCESS) {

						AS_CHECK(executingScriptContext->Prepare(menu));

						AS_CHECK(executingScriptContext->SetArgObject(0, data));

						AS_CHECK(executingScriptContext->Execute());

						executingScriptContext->PopState();
					} else {
						ImGui::Text("Something failed");
					}
					ImGui::EndPopup();
				}
				ImGui::PopStyleVar();

				ImGui::Dummy(ImVec2(0, 10));
				ImGui::PushID(txt.c_str());
				if (executingScriptContext &&
				    executingScriptContext->PushState() == asSUCCESS) {

					AS_CHECK(executingScriptContext->Prepare(func));

					AS_CHECK(executingScriptContext->SetArgObject(0, data));

					AS_CHECK(executingScriptContext->Execute());

					executingScriptContext->PopState();
				} else {
					ImGui::Text("Something failed");
				}

				ImGui::Dummy(ImVec2(0, 10));
				ImGui::PopID();
				ImGui::TreePop();

				ImGui::PopStyleVar(2);
				return true;
			}

			ImGui::PopStyleVar(2);
			return false;
		}

		void setupColumns(int i) { ImGui::Columns(i, nullptr, false); }

		void setupAutomaticColumns(int pixelSize) {
			float width = ImGui::GetWindowContentRegionWidth();

			if (width < pixelSize) {
				ImGui::Columns();
				return;
			}

			int cols = (int)(width / (pixelSize));
			float componentWidth = width / (float)cols;

			ImGui::Columns(cols, 0, false);
		}

		void childWindow(CScriptAny* data, asIScriptFunction* func, int width,
		                 int height, bool border) {}

		void endColumns() { ImGui::Columns(); }

		void nextColumn() { ImGui::NextColumn(); }

		void space() { ImGui::Dummy(ImVec2(10, 10)); }

		void space_params(int x, int y) { ImGui::Dummy(ImVec2(x, y)); }
	} // namespace EditorEngine
} // namespace Deer