#pragma once
#include "Shader.h"
#include "Mesh.h"
#include <string>
#include <memory>
#include <unordered_map>
#include <filesystem>
#include <expected>

// Forward declarations
class Texture;

// Modern resource manager using C++23 features
class ResourceManager {
public:
    // Delete constructor - this is a static-only class
    ResourceManager() = delete;
    ~ResourceManager() = delete;
    ResourceManager(const ResourceManager&) = delete;
    ResourceManager& operator=(const ResourceManager&) = delete;



    static bool IsHotReloadEnabled();

    // Shader management using std::expected (C++23)
    [[nodiscard]] static std::expected<std::shared_ptr<Shader>, std::string> 
        LoadShader(const std::string& name, 
                  const std::filesystem::path& vertex_path,
                  const std::filesystem::path& fragment_path);

    [[nodiscard]] static std::expected<std::shared_ptr<Shader>, std::string>
        LoadShader(const std::string& name,
                  const std::filesystem::path& vertex_path,
                  const std::filesystem::path& geometry_path,
                  const std::filesystem::path& fragment_path);

    [[nodiscard]] static std::shared_ptr<Shader> GetShader(const std::string& name);
    
    // Texture management
    [[nodiscard]] static std::expected<std::shared_ptr<Texture>, std::string>
        LoadTexture(const std::string& name, const std::filesystem::path& path, bool generate_mipmaps = true);
    
    [[nodiscard]] static std::shared_ptr<Texture> GetTexture(const std::string& name);

    // Mesh management (for commonly used meshes)
    static void RegisterMesh(const std::string& name, std::shared_ptr<Mesh> mesh);
    [[nodiscard]] static std::shared_ptr<Mesh> GetMesh(const std::string& name);

    // Resource cleanup
    static void ClearShaders();
    static void ClearTextures();
    static void ClearMeshes();
    static void ClearAll();

    // Resource information
    [[nodiscard]] static size_t GetShaderCount() { return shaders_.size(); }
    [[nodiscard]] static size_t GetTextureCount() { return textures_.size(); }
    [[nodiscard]] static size_t GetMeshCount() { return meshes_.size(); }
    
    // Debug functions
    static void PrintResourceInfo();
    [[nodiscard]] static bool HasShader(const std::string& name);
    [[nodiscard]] static bool HasTexture(const std::string& name);
    [[nodiscard]] static bool HasMesh(const std::string& name);

    // Batch loading functions
    static void LoadShadersFromDirectory(const std::filesystem::path& directory);
    static void LoadTexturesFromDirectory(const std::filesystem::path& directory);

    // Hot reloading support (for development)
    static void EnableHotReload(bool enable) { hot_reload_enabled_ = enable; }
    static void CheckForChanges(); // Call this each frame in debug builds

private:
    static std::unordered_map<std::string, std::shared_ptr<Shader>> shaders_;
    static std::unordered_map<std::string, std::shared_ptr<Texture>> textures_;
    static std::unordered_map<std::string, std::shared_ptr<Mesh>> meshes_;
    
    // Hot reload support
    static bool hot_reload_enabled_;
    static std::unordered_map<std::string, std::filesystem::file_time_type> shader_timestamps_;
    static std::unordered_map<std::string, std::filesystem::file_time_type> texture_timestamps_;

    static std::unordered_map<std::string, std::filesystem::path> texture_paths_;


    // Helper functions
    [[nodiscard]] static bool IsShaderFile(const std::filesystem::path& path);
    [[nodiscard]] static bool IsTextureFile(const std::filesystem::path& path);
    static void ReloadShader(const std::string& name);
    static void ReloadTexture(const std::string& name);

    static std::unordered_map<std::string, std::filesystem::path> shader_paths_;
};