#include "Deer/DataStore.h"
#include "Deer/Log.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/API/Asset.h"
#include "DeerStudio/EditorEngine/DockPanel/DockPanelObject.h"

namespace Deer {
	namespace EditorEngine {

		const char* getAssetTypePath(AssetType resource) {
			switch (resource) {
			case AssetType::NONE:
				return nullptr;

			case AssetType::MESH:
				return DEER_MESH_PATH;

			case AssetType::SHADER:
				return DEER_SHADER_PATH;
			}

			return nullptr;
		}

		const char* getAssetTypeExtension(AssetType resource) {
			switch (resource) {
			case AssetType::NONE:
				return nullptr;

			case AssetType::MESH:
				return DEER_MESH_EXTENSION;

			case AssetType::SHADER:
				return DEER_SHADER_EXTENSION;
			}

			return nullptr;
		}

		const char* getAssetTypeName(AssetType resource) {
			switch (resource) {
			case AssetType::NONE:
				return "???";

			case AssetType::MESH:
				return "Mesh";

			case AssetType::SHADER:
				return "Shader";
			}

			return nullptr;
		}

		int getAssetCount(AssetType type, std::string& dir) {
			const char* resourcePath = getAssetTypePath(type);
			const char* resourceExtension = getAssetTypeExtension(type);

			if (!resourcePath || !resourceExtension) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid resource type calling getAssetCount(..)");
				if (currentDockPanelExecution) {
					currentDockPanelExecution->invalidate();
				}
				return 0;
			}

			return DataStore::getDirData(resourcePath, dir, resourceExtension)
			    .elements.size();
		}

		std::string getAssetNameById(AssetType type, std::string& dir, int i) {
			const char* resourcePath = getAssetTypePath(type);
			const char* resourceExtension = getAssetTypeExtension(type);

			if (!resourcePath || !resourceExtension) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid resource type calling getAssetNameById(..)");
				if (currentDockPanelExecution) {
					currentDockPanelExecution->invalidate();
				}
				return "";
			}

			const DirectoryData& dirData =
			    DataStore::getDirData(resourcePath, dir, resourceExtension);
			if (i < 0 || i >= dirData.elements.size()) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid element id {3} calling getAssetNameById(..) "
				    "for type {0} and path {1}, element count on that dir is "
				    "{2}",
				    getAssetTypeName(type), dir.c_str(),
				    dirData.elements.size(), i);

				if (currentDockPanelExecution)
					currentDockPanelExecution->invalidate();
				return "";
			}

			return dirData.elements[i].stem().string();
		}

		std::string getParentPath(std::string& path) {
			return Path(path).parent_path().string();
		}

		std::string getParentPathName(std::string& path) {
			return Path(path).parent_path().stem().string();
		}

		std::string getAssetTypePathById(AssetType type, std::string& dir,
		                                 int i) {
			const char* resourcePath = getAssetTypePath(type);
			const char* resourceExtension = getAssetTypeExtension(type);

			if (!resourcePath || !resourceExtension) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid resource type calling getAssetTypePathById(..)");
				if (currentDockPanelExecution) {
					currentDockPanelExecution->invalidate();
				}
				return "";
			}

			const DirectoryData& dirData =
			    DataStore::getDirData(resourcePath, dir, resourceExtension);
			if (i < 0 || i >= dirData.elements.size()) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid element id {3} calling getAssetTypePathById(..) "
				    "for type {0} and path {1}, element count on that dir is "
				    "{2}",
				    getAssetTypeName(type), dir.c_str(),
				    dirData.elements.size(), i);

				if (currentDockPanelExecution)
					currentDockPanelExecution->invalidate();
				return "";
			}

			return dirData.elements[i].string();
		}

		int getDirCount(AssetType type, std::string& dir) {
			const char* resourcePath = getAssetTypePath(type);
			const char* resourceExtension = getAssetTypeExtension(type);

			if (!resourcePath || !resourceExtension) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid resource type calling getDirCount(..)");
				if (currentDockPanelExecution) {
					currentDockPanelExecution->invalidate();
				}
				return 0;
			}

			return DataStore::getDirData(resourcePath, dir, resourceExtension)
			    .dirs.size();
		}

		std::string getDirPathById(AssetType type, std::string& dir, int i) {
			const char* resourcePath = getAssetTypePath(type);
			const char* resourceExtension = getAssetTypeExtension(type);

			if (!resourcePath || !resourceExtension) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid resource type calling getDirPathById(..)");
				if (currentDockPanelExecution) {
					currentDockPanelExecution->invalidate();
				}
				return "";
			}

			const DirectoryData& dirData =
			    DataStore::getDirData(resourcePath, dir, resourceExtension);
			if (i < 0 || i >= dirData.dirs.size()) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid element id {3} calling getDirPathById(..) for "
				    "type {0} and path {1}, sub_dir count on that dir is {2}",
				    getAssetTypeName(type), dir.c_str(), dirData.dirs.size(),
				    i);

				if (currentDockPanelExecution)
					currentDockPanelExecution->invalidate();
				return "";
			}

			return dirData.dirs[i].string();
		}

		std::string getDirNameById(AssetType type, std::string& dir, int i) {
			const char* resourcePath = getAssetTypePath(type);
			const char* resourceExtension = getAssetTypeExtension(type);

			if (!resourcePath || !resourceExtension) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid resource type calling getDirNameById(..)");
				if (currentDockPanelExecution) {
					currentDockPanelExecution->invalidate();
				}
				return "";
			}

			const DirectoryData& dirData =
			    DataStore::getDirData(resourcePath, dir, resourceExtension);
			if (i < 0 || i >= dirData.dirs.size()) {
				DEER_EDITOR_ENGINE_ERROR(
				    "Invalid element id {3} calling getDirPathById(..) for "
				    "type {0} and path {1}, sub_dir count on that dir is {2}",
				    getAssetTypeName(type), dir.c_str(), dirData.dirs.size(),
				    i);

				if (currentDockPanelExecution)
					currentDockPanelExecution->invalidate();
				return "";
			}

			return dirData.dirs[i].stem().string();
		}
	} // namespace EditorEngine
} // namespace Deer