#pragma once

#include "core/world/Area.hpp"
#include "core/utils/mutex.hpp"
#include "./Region.hpp"
#include "core/world/Registry.hpp"
#include "core/world/generator/Abstract.hpp"

namespace world::server {

    /// Area (aka big group of server::Chunk)
    struct Area final: public world::Area {
    public:
        using regions_t = robin_hood::unordered_map<region_pos, std::shared_ptr<Region>>;

        struct params {
            int radius;
            size_t genId;
            std::vector<char> params;
        };

        Area(const params& p): world::Area(p.radius), generator(world::module::Registry::Get()->createGenerator(p.genId, p.params.data())), copy(p) { }

        std::shared_ptr<Region> getRegion(const std::string& folderPath, const area_region_ref &);
        mutex::shared_guard<regions_t>::handle getRegions() { return regions.lock(); }
        mutex::shared_guard<regions_t>::shared_handle getRegions() const { return regions.lock_shared(); }

        inline const std::unique_ptr<generator::Abstract>& getGenerator() const { return generator; }

        inline params getParams() const { return copy; }

        std::optional<double> getCurvature() const override { return generator->getCurvature(); }

        inline const glm::vec3 getGravity(const voxel_pos& p) const { return generator->getGravity(p); }

    private:
        mutex::shared_guard<regions_t> regions;

        std::unique_ptr<generator::Abstract> generator;
        const params copy;
    };
}