#pragma once

#include "forward.h"
#include "Voxel.hpp"
#include <variant>
#include "../flags.hpp"
#include "../geometry/Shapes.hpp"

/// Client action on world
namespace world::action {

namespace part {
struct Ping { };
}

struct Fill: part::Ping {
    Fill(const area_<voxel_pos> &pos, const Voxel &val): pos(pos), val(val) {}

    const area_<voxel_pos> pos;
    const Voxel val;
};

enum class Shape: uint8_t {
    Cube,
    RawSphere,
    SmoothSphere,
    /*CylinderX,
    CylinderY,
    CylinderZ,
    ConePX,
    ConeNX,
    ConePY,
    ConeNY,
    ConePZ,
    ConeNZ,
    */
};
static const std::array<std::string, 3> SHAPES = {"Cube", "Raw Sphere", "Smooth Sphere"};
static _FORCE_INLINE_ geometry::Shape ToGeometry(Shape shape) {
    switch (shape) {
    case Shape::RawSphere:
        return geometry::Shape::Sphere;
    case Shape::SmoothSphere:
        return geometry::Shape::Sphere;
    default:
        return geometry::Shape::Cube;
    }
}

struct FillShape: Fill {
    FillShape(const area_<voxel_pos> &pos, const Voxel &val, Shape shape, uint8_t radius):
        Fill(pos, val), shape(shape), radius(radius) {}

    const Shape shape;
    const uint8_t radius;
};
struct Move: part::Ping {
    Move(const voxel_pos& pos): pos(pos) { }

    const voxel_pos pos;
};
struct Message: part::Ping {
    Message(const std::string& text): text(text) { }

    const std::string text;
};

using packet = std::variant<Move, Message, Fill, FillShape>;
}