#ifndef FLUID_REGISTRY_HPP_
#define FLUID_REGISTRY_HPP_

#include <unordered_map>

#include <Fluid/Fluid.hpp>
#include <BlockAtlas/BlockAtlas.hpp>

/**
 * @brief Represents the fluid registry.
 * 
 * To access the registry, use the global singleton instance `fluidRegistry`.
 */
class FluidRegistry
{
private:
    std::unordered_map<std::string, Fluid*> fluids;

protected:
    /**
     * @brief Register a fluid.
     * 
     * @tparam TFluid The fluid class.
     * @param name The fluid name.
     * @param args Arguments to the constructor (besides the name).
     */
    template<typename TFluid, typename... TArgs>
    TFluid& registerFluid(std::string name, TArgs&&... args)
    {
        TFluid *fluid = new TFluid(name, args...);
        fluids[name] = fluid;
        return *fluid;
    }

public:
    ~FluidRegistry();

    /**
     * @brief Register all fluids.
     */
    void registerAllFluids();

    /**
     * @brief Get a fluid by name.
     * 
     * Returns `nullptr` if the fluid does not exist.
     */
    Fluid* getFluidByName(std::string name);

    /**
     * @brief Add the callbacks to be called during preloading.
     */
    void addLoadingTasks(std::vector<std::function<void(std::atomic<unsigned int> &)>> &tasks);
    
    int getTotalFluids();
    void forEachFluid(std::function<void(Fluid*)> callback);

    friend class BlockRegistry;
};

/**
 * @brief The singleton fluid registry instance.
 */
extern FluidRegistry fluidRegistry;

#endif