#pragma once

#include "./Chunk.hpp"
#include "core/world/EdittableChunk.hpp"

namespace world::server {
    // Server and Client merged chunk
    class SharedChunk final: public Chunk {
    public:
        SharedChunk(): Chunk(new world::ChunkEdits(this)) { }
        SharedChunk(const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd): Chunk(new world::ChunkEdits(this), pos, rnd) { }
        SharedChunk(std::istream &str, bool rle = RLE): Chunk(new world::ChunkEdits(this), str, rle) { }

        /// Break voxel
        std::optional<Item> replace(chunk_voxel_idx idx, const Voxel &val, float delay = 0) override {
            const auto res = voxels[idx];
            set(idx, val);
            if (res.value != voxels[idx].value) {
                setEdits()->add(world::ChunkEdits::Edit{res, delay, idx});
            }
            return {Item{res.density(), res.material()}};
        }
    };

    /// Build really EdittableChunk for internal client
    struct SharedChunkFactory final: public ChunkFactory {
        std::shared_ptr<Chunk> create(const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd) const override {
            return std::make_shared<SharedChunk>(pos, rnd);
        }
        std::shared_ptr<Chunk> create(std::istream &str) const override { return std::make_shared<SharedChunk>(str); }
        std::shared_ptr<Chunk> create() const override { return std::make_shared<SharedChunk>(); }
    };
}