#include "../include/WorldData.h"

namespace warfactory {

WorldData::WorldData(int width, int height)
    : ASerializable("world_data"), terrain_map(std::make_unique<GMap>(width, height)), world_width(width), world_height(height) {
}

WorldData::~WorldData() = default;

// Move constructor
WorldData::WorldData(WorldData&& other) noexcept
    : ASerializable("world_data"), terrain_map(std::move(other.terrain_map)),
      world_width(other.world_width), world_height(other.world_height) {
    other.world_width = 0;
    other.world_height = 0;
}

// Move assignment operator
WorldData& WorldData::operator=(WorldData&& other) noexcept {
    if (this != &other) {
        terrain_map = std::move(other.terrain_map);
        world_width = other.world_width;
        world_height = other.world_height;

        other.world_width = 0;
        other.world_height = 0;
    }
    return *this;
}

// ========================================
// MAP ACCESS
// ========================================

GMap* WorldData::getTerrainMap() {
    return terrain_map.get();
}

const GMap* WorldData::getTerrainMap() const {
    return terrain_map.get();
}

GTile* WorldData::getTile(int x, int y) {
    return terrain_map ? terrain_map->getTile(x, y) : nullptr;
}

const GTile* WorldData::getTile(int x, int y) const {
    return terrain_map ? terrain_map->getTile(x, y) : nullptr;
}

bool WorldData::isValidCoordinate(int x, int y) const {
    return terrain_map ? terrain_map->isValidCoordinate(x, y) : false;
}

// ========================================
// WORLD STATISTICS
// ========================================

float WorldData::getAverageElevation() const {
    return terrain_map ? terrain_map->getAverageElevation() : 0.0f;
}

float WorldData::getAverageTemperature() const {
    return terrain_map ? terrain_map->getAverageTemperature() : 0.0f;
}

int WorldData::getTotalTileCount() const {
    return world_width * world_height;
}

// ========================================
// SERIALIZATION
// ========================================

json WorldData::serialize() const {
    json data;
    data["world_width"] = world_width;
    data["world_height"] = world_height;

    if (terrain_map) {
        data["terrain_map"] = terrain_map->serialize();
    } else {
        data["terrain_map"] = nullptr;
    }

    return data;
}

void WorldData::deserialize(const json& data) {
    world_width = data.at("world_width").get<int>();
    world_height = data.at("world_height").get<int>();

    const json& terrain_data = data.at("terrain_map");
    if (!terrain_data.is_null()) {
        terrain_map = std::make_unique<GMap>(world_width, world_height);
        terrain_map->deserialize(terrain_data);
    } else {
        terrain_map.reset();
    }
}

} // namespace warfactory