#include "DeerStudio/StudioAPI/Layout.h"
#include "DeerStudio/AngelScriptEngine.h"
#include "DeerStudio/AngelScriptEngine/ErrorHandle.h"

#include "angelscript.h"
#include "imgui.h"
#include "scriptany.h"

namespace Deer {
	namespace StudioAPI {
		void treeNodeLeaf(std::string& txt, bool active) {
			ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf |
			                           ImGuiTreeNodeFlags_NoTreePushOnOpen |
			                           ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Bullet | 
									   ImGuiTreeNodeFlags_DrawLinesToNodes;

			if (active)
				flags |= ImGuiTreeNodeFlags_Selected;

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

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

			if (active)
				flags |= ImGuiTreeNodeFlags_Selected;

			if (ImGui::TreeNodeEx(txt.c_str(), flags)) {
				ImGui::PushID(txt.c_str());

				if (AngelScriptEngine::scriptContext && AngelScriptEngine::scriptContext->PushState() == asSUCCESS) {

					AS_CHECK_ADDITIONAL_INFO(AngelScriptEngine::scriptContext->Prepare(&func), func.GetDeclaration());
					AS_CHECK_ADDITIONAL_INFO(AngelScriptEngine::scriptContext->Execute(), func.GetDeclaration());

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

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

				ImGui::PopStyleVar();
				return true;
			}

			ImGui::PopStyleVar();
			return false;
		}

		bool componentNode(std::string& txt, asIScriptFunction* func) {
			ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));

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

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

					AS_CHECK(AngelScriptEngine::scriptContext->Prepare(func));
					AS_CHECK(AngelScriptEngine::scriptContext->Execute());

					AngelScriptEngine::scriptContext->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 componentNodeContextMenu(std::string& txt, 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_AllowOverlap |
			                           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 (AngelScriptEngine::scriptContext &&
					    AngelScriptEngine::scriptContext->PushState() == asSUCCESS) {

						AS_CHECK(AngelScriptEngine::scriptContext->Prepare(menu));
						AS_CHECK(AngelScriptEngine::scriptContext->Execute());

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

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

					AS_CHECK(AngelScriptEngine::scriptContext->Prepare(func));
					AS_CHECK(AngelScriptEngine::scriptContext->Execute());

					AngelScriptEngine::scriptContext->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 columns(int i) { ImGui::Columns(i, nullptr, false); }

		void automaticColumns(int pixelSize) {
			float width = ImGui::GetWindowContentRegionMax().x;

			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 StudioAPI
} // namespace Deer