/// AssetManager.h
#pragma once

#include <string>
#include <memory>
#include <unordered_map>
#include <queue>
#include <mutex>
#include <filesystem>
#include <thread>
#include <atomic>
#include <vector>
#include <cstdint>

namespace OX
{
    class Asset;

    struct ResourceTreeNode
    {
        std::string name;
        std::string path;
        bool isDirectory = false;
        std::vector<std::shared_ptr<ResourceTreeNode> > children;
    };

    class AssetManager
    {
    public:
        // -- Lifecycle --
        static void Init(const std::string &projectRoot);

        static void Shutdown();

        static void Tick();

        static void Rescan();


        static size_t GetTotalTexturesToLoad() { return s_TotalTexturesToLoad.load(); }
        static size_t GetLoadedTexturesCount()  { return s_LoadedTexturesCount.load(); }

        // -- Queries --
        // Lookup by virtual path ("res://…") or real FS path.
        static std::shared_ptr<Asset> Get(const std::string &path);

        static std::shared_ptr<ResourceTreeNode> GetFileTree();

        static void SaveAssetPack(const std::string &outputPath);

        static std::mutex s_TreeMutex;

    private:
        struct AssetMetadata
        {
            std::string type;
            std::string absolutePath;
        };

        struct PendingTexture
        {
            std::string id;
            int width, height, channels;
            unsigned char *data;
        };

        static void BackgroundScan();

        static void AddToTree(const std::string &virtualPath, bool isDir);

        static std::string DetectAssetType(const std::filesystem::path &path);

        static std::string MakeVirtualPath(const std::filesystem::path &full);

        // loaded assets & metadata
        static std::unordered_map<std::string, std::string> s_PathToID;
        static std::unordered_map<std::string, std::shared_ptr<Asset> > s_LoadedAssets;
        static std::unordered_map<std::string, AssetMetadata> s_MetadataMap;
        static std::mutex s_AssetMutex;

        // directory tree
        static std::shared_ptr<ResourceTreeNode> s_FileTree;

        // background scan
        static std::filesystem::path s_ProjectRoot;
        static std::atomic<bool> s_Scanning;
        static std::thread s_ScanThread;

        // texture upload queue
        static std::queue<PendingTexture> s_TextureQueue;
        static std::mutex s_QueueMutex;

        static std::atomic<size_t> s_TotalTexturesToLoad;
        static std::atomic<size_t> s_LoadedTexturesCount;
    };
}
