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

namespace Deer {
    namespace EditorEngine {
        
        const char* getResourcePath(ResourceType resource) {
            switch (resource)
            {
            case ResourceType::NOTHING:
                return nullptr;
            
            case ResourceType::MESH :
                return DEER_MESH_PATH;

            case ResourceType::SHADER :
                return DEER_SHADER_PATH;
            }

            return nullptr;
        }

        const char* getResourceExtension(ResourceType resource) {
            switch (resource)
            {
            case ResourceType::NOTHING:
                return nullptr;
            
            case ResourceType::MESH :
                return DEER_MESH_EXTENSION;

            case ResourceType::SHADER :
                return DEER_SHADER_EXTENSION;
            }

            return nullptr;
        }

        const char* getResourceName(ResourceType resource) {
            switch (resource)
            {
            case ResourceType::NOTHING:
                return "???";
            
            case ResourceType::MESH :
                return "Mesh";

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

            return nullptr;
        }

        int getResourceCount(ResourceType type, std::string& dir) {
            const char* resourcePath = getResourcePath(type);
            const char* resourceExtension = getResourceExtension(type);

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

            return DataStore::getDirData(resourcePath, dir, resourceExtension).elements.size();
        }
        
        std::string getResourceNameById(ResourceType type, std::string& dir, int i) {
            const char* resourcePath = getResourcePath(type);
            const char* resourceExtension = getResourceExtension(type);

            if (!resourcePath || !resourceExtension) {
                DEER_EDITOR_ENGINE_ERROR("Invalid resource type calling getResourceNameById(..)");
                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 getResourceNameById(..) for type {0} and path {1}, element count on that dir is {2}",
                    getResourceName(type),
                    dir.c_str(),
                    dirData.elements.size(),
                    i
                );
                
                if (currentDockPanelExecution) 
                    currentDockPanelExecution->invalidate();
                return "";
            }

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

        std::string getResourcePathById(ResourceType type, std::string& dir, int i) {
            const char* resourcePath = getResourcePath(type);
            const char* resourceExtension = getResourceExtension(type);

            if (!resourcePath || !resourceExtension) {
                DEER_EDITOR_ENGINE_ERROR("Invalid resource type calling getResourcePathById(..)");
                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 getResourcePathById(..) for type {0} and path {1}, element count on that dir is {2}",
                    getResourceName(type),
                    dir.c_str(),
                    dirData.elements.size(),
                    i
                );
                
                if (currentDockPanelExecution) 
                    currentDockPanelExecution->invalidate();
                return "";
            }

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

        int getDirCount(ResourceType type, std::string& dir) {
            const char* resourcePath = getResourcePath(type);
            const char* resourceExtension = getResourceExtension(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(ResourceType type, std::string& dir, int i) {
            const char* resourcePath = getResourcePath(type);
            const char* resourceExtension = getResourceExtension(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}",
                    getResourceName(type),
                    dir.c_str(),
                    dirData.dirs.size(),
                    i)
                ;
                
                if (currentDockPanelExecution) 
                    currentDockPanelExecution->invalidate();
                return "";
            }

            return dirData.dirs[i].string();
        }
        
        std::string getDirNameById(ResourceType type, std::string& dir, int i) {
            const char* resourcePath = getResourcePath(type);
            const char* resourceExtension = getResourceExtension(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}",
                    getResourceName(type),
                    dir.c_str(),
                    dirData.dirs.size(),
                    i
                );
                
                if (currentDockPanelExecution) 
                    currentDockPanelExecution->invalidate();
                return "";
            }

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