#pragma once

#include "../../core/world/Area.hpp"
#include <shared_mutex_guarded.h>
using namespace libguarded;
#include "region/index.hpp"
#include "generator.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 {
            voxel_pos center;
            int radius;
            generator::params properties;
        };

        Area(const params& p): world::Area(p.center, p.radius), generator(generator::load(p.properties)), generator_properties(p.properties) { }

        std::shared_ptr<Region> getRegion(const std::string& folderPath, const area_<region_pos> &);
        shared_guarded<regions_t>::handle getRegions() { return regions.lock(); }

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

        inline params getParams() const { return params{getOffset().as_voxel(), getChunks().getRadius(), generator_properties}; }

        std::optional<double> getCurvature() const override { return GetCurvature(generator_properties); }
        static std::optional<double> GetCurvature(const generator::params &);

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

    private:
        shared_guarded<regions_t> regions;

        std::unique_ptr<generator::Abstract> generator;
        const generator::params generator_properties; //MAYBE: useless copy
    };
}