/******************************************************************************
*	File		-	content_manager.h
*	Author		-	Joey Pollack
*	Date		-	2022/02/22 (y/m/d)
*	Mod Date	-	2022/02/22 (y/m/d)
*	Description	-	Keeps track of all resource files in the project.
*                   Reads/Writes meta-data to the contents_meta.xml file.
*                   Also manages the physical location of each asset file.
******************************************************************************/

#ifndef CONTENT_MANAGER_H_
#define CONTENT_MANAGER_H_

#include "definitions.h"
#include <filesystem>
#include <string>
#include <utils/op_res.h>
#include <map>
#include <vector>
#include <nlohmann/json.hpp>

namespace lunarium { namespace editor 
{

    class Project;
    class EditorAsset;

    class ContentManager
    {
    public:

        static ContentManager& GetInstance();
        static void FreeInstance();

        [[nodiscard]] OpRes Load(Project* project);
        [[nodiscard]] OpRes Save();
        void Unload();

        void GetAllAssetIDs(std::vector<uint64_t>& container) const;
        void GetAllAssetsByType(std::vector<EditorAsset*>& container, AssetType type) const;
        void GetAllAssetsInDirectory(std::vector<EditorAsset*>& container, std::filesystem::path dir); // dir should be relative to the asset dir
        EditorAsset* GetAsset(uint64_t id);


        /// Add an asset that was generated by the editor (like tile maps or scripts)
        [[nodiscard]] OpRes AddGeneratedAsset(EditorAsset* asset, uint64_t& id);

        /// Import a raw asset file from outside of the project (like image or sound files)
        /// file: the full path to the raw file
        /// to_location: the location inside the project's asset directory to import to (this MUST be a relative path starting in the Asset dir)
        [[nodiscard]] OpRes ImportFile(std::filesystem::path file, std::filesystem::path to_location, AssetType type, uint64_t& id);
        void RemoveAsset(uint64_t asset_id);

    private:
        static ContentManager* mpInstance;
        Project* mpProject;
        std::filesystem::path mContentFile;
        std::map<uint64_t, EditorAsset*> mAssets;
        uint64_t mNextID;

    private:
        ContentManager();
        ContentManager(ContentManager&) = delete;
        ContentManager& operator=(const ContentManager&) = delete;

    private: // Helpers
        [[nodiscard]] bool IsValidAsset(nlohmann::json& node);
        [[nodiscord]] EditorAsset* CreateAsset(AssetType type);
        void FreeAssets();


    };
}}

#endif  // CONTENT_MANAGER_H_