#include "Deer/Log.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/AngelscriptPredefined.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "DeerStudio/EditorEngine/ServiceScript/ServiceScriptContext.h"
#include "DeerStudio/EditorEngine/ServiceScript/ServiceScriptInfo.h"

#include "Deer/DataStore.h"
#include "Deer/Path.h"

#include "angelscript.h"
#include "scriptbuilder.h"

#include <filesystem>
#include <iostream>
#include <string>
#include <vector>

namespace fs = std::filesystem;

namespace Deer {
	void EditorEngine::loadServiceScripts() {
		Path path = DataStore::rootPath / DEER_EDITOR_SERVICE_PATH;

		if (!fs::exists(path) || !fs::is_directory(path)) {
			DEER_EDITOR_ENGINE_ERROR(
			    "Could not find folder " DEER_EDITOR_SERVICE_PATH);
			return;
		}

		for (const auto &_dir : fs::directory_iterator(path)) {
			Path panelInfo_path = _dir.path() / "ServiceScript.json";

			// A panel info is neded to load a panel
			if (!fs::exists(panelInfo_path) ||
			    !fs::is_regular_file(panelInfo_path)) {
				DEER_EDITOR_ENGINE_WARN("Editor engine did not find "
				                        "ServiceScript.json in folder {0}",
				                        panelInfo_path.c_str());
				continue;
			}

			ServiceScriptInfo *serviceScriptInfo =
			    loadServiceScriptInfo(panelInfo_path);
			if (serviceScriptInfo->name == "null") {
				DEER_EDITOR_ENGINE_ERROR(
				    "Failed to load service script module from {0},\n "
				    "incorrect ServiceScript.json file",
				    path.string().c_str());
				delete serviceScriptInfo;
				continue;
			}

			saveAngelscriptPredefined(_dir);

			int r;
			r = scriptBuilder.StartNewModule(scriptEngine,
			                                 serviceScriptInfo->name.c_str());
			if (r < 0) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Failed to create module for service script module {0}",
				    path.string().c_str());
				delete serviceScriptInfo;
				continue;
			}

			for (const auto &entry : fs::recursive_directory_iterator(_dir)) {
				if (entry.is_regular_file() &&
				    entry.path().extension() == ".as") {
					r = scriptBuilder.AddSectionFromFile(
					    entry.path().string().c_str());
					if (r < 0) {
						DEER_EDITOR_ENGINE_ERROR(
						    "Failed loading script for module {0}\nscript: {1}",
						    path.string().c_str(),
						    entry.path().string().c_str());
					}
				}
			}

			r = scriptBuilder.BuildModule();
			if (r < 0) {
				DEER_EDITOR_ENGINE_ERROR("Failed compiling module {0}",
				                         path.string().c_str());
				delete serviceScriptInfo;
				continue;
			}

			serviceScriptModules.push_back(ServiceScriptContext(
			    scriptEngine->GetModule(serviceScriptInfo->name.c_str()),
			    serviceScriptInfo));

			serviceScriptModules.back().bindFunctions();
		}
	}
} // namespace Deer