#pragma once

#include "./Area.hpp"
#include "core/world/Elements.hpp"
#include <memory>

namespace io { class ifstream; class ofstream; }
namespace world::server {

/// Handle elements pseudo ECS
class Elements final: public world::EdittableElements {
public:
    Elements();

    void readIndex(io::ifstream&);
    void writeIndex(io::ofstream&) const;

    area_id createArea(const start_point&, const Area::params& params);
    part_id createPart(const start_point&, glm::usvec3 size);
    instance_id createInstance(const start_point&, model_id model, uint8_t flag = 0);

    NodeOf<Area>* findArea(area_id i) {
        assert(Is<Type::Area>(i.val));
        return NodeOf<Area>::Make(findNode(i.val));
    }
    const NodeOf<Area>* findArea(area_id i) const {
        assert(Is<Type::Area>(i.val));
        return NodeOf<Area>::Make(findNode(i.val));
    }

private:
    area_id createAreaAt(generational::id::idx_t, uint8_t flag, const start_point&, const Area::params& params);
    part_id createPartAt(generational::id::idx_t, uint8_t flag, const start_point&, glm::usvec3 size);
    instance_id createInstanceAt(generational::id::idx_t i, uint8_t flag, const start_point&, model_id model);
};
}
