//
// Created by Dan Crosby on 3/29/21.
//

#include "UnitConversions.hpp"

namespace shardok {

using Coords = net::eagle0::shardok::storage::fb::Coords;

auto ConvertBattalion(const net::eagle0::common::CommonBattalion &battalion) -> Battalion {
    Battalion shardokBattalion{};

    shardokBattalion.mutate_eagle_battalion_id(battalion.eagle_battalion_id());
    shardokBattalion.mutate_size(battalion.size());
    shardokBattalion.mutate_type(
            static_cast<net::eagle0::shardok::storage::fb::BattalionTypeId>(battalion.type()));
    shardokBattalion.mutate_morale(battalion.morale());
    shardokBattalion.mutate_armament(battalion.armament());
    shardokBattalion.mutate_training(battalion.training());

    return shardokBattalion;
}

auto ConvertHero(const net::eagle0::common::CommonHero &hero) -> Hero {
    Hero shardokHero{};

    shardokHero.mutate_eagle_hero_id(hero.eagle_hero_id());
    shardokHero.mutate_is_vip(hero.is_vip());

    shardokHero.mutable_profession_info().mutate_profession(
            static_cast<net::eagle0::shardok::storage::fb::Profession>(hero.profession()));
    shardokHero.mutable_profession_info().mutate_meteor_cast_state(
            net::eagle0::shardok::storage::fb::MultiroundMagicState_NONE);
    shardokHero.mutable_profession_info().mutable_cast_target() = Coords(-1, -1);

    shardokHero.mutable_control_info().mutate_controlled_unit_id(-1);
    shardokHero.mutable_control_info().mutate_controlled_this_round(false);

    shardokHero.mutate_strength(hero.strength());
    shardokHero.mutate_strength_xp(hero.strength_xp());

    shardokHero.mutate_agility(hero.agility());
    shardokHero.mutate_agility_xp(hero.agility_xp());

    shardokHero.mutate_constitution(hero.constitution());
    shardokHero.mutate_constitution_xp(hero.constitution_xp());

    shardokHero.mutate_charisma(hero.charisma());
    shardokHero.mutate_charisma_xp(hero.charisma_xp());

    shardokHero.mutate_wisdom(hero.wisdom());
    shardokHero.mutate_wisdom_xp(hero.wisdom_xp());

    shardokHero.mutate_integrity(hero.integrity());
    shardokHero.mutate_ambition(hero.ambition());
    shardokHero.mutate_gregariousness(hero.gregariousness());
    shardokHero.mutate_bravery(hero.bravery());

    shardokHero.mutate_vigor(hero.vigor());
    shardokHero.mutate_starting_vigor(hero.vigor());

    return shardokHero;
}

auto ConvertUnit(
        const net::eagle0::common::CommonUnit &unit,
        const PlayerId shardokPlayerId,
        const vector<PlayerId> &allPlayerIds) -> Unit {
    Unit shardokUnit{};

    shardokUnit.mutate_player_id(shardokPlayerId);

    // Range check eagle_player_id for int8 conversion
    int32_t eagle_id = unit.eagle_player_id();
    if (eagle_id < -128 || eagle_id > 127) {
        throw std::runtime_error(
                "eagle_player_id " + std::to_string(eagle_id) + " out of int8 range");
    }
    shardokUnit.mutate_eagle_player_id(static_cast<int8_t>(eagle_id));
    shardokUnit.mutate_hidden(false);
    shardokUnit.mutate_fortified(false);
    if (unit.has_hero()) {
        shardokUnit.mutate_has_attached_hero(true);
        shardokUnit.mutable_attached_hero() = ConvertHero(unit.hero());
    } else {
        shardokUnit.mutate_has_attached_hero(false);
    }
    shardokUnit.mutate_commanding_unit_id(-1);
    shardokUnit.mutable_location() = Coords(-1, -1);
    shardokUnit.mutable_battalion() = ConvertBattalion(unit.battalion());
    shardokUnit.mutate_remaining_action_points(0);
    shardokUnit.mutate_stun_rounds_remaining(0);

    for (const PlayerId pid : allPlayerIds) {
        shardokUnit.mutable_opponent_knowledge()->Mutate(pid, 0);
    }

    shardokUnit.mutate_has_moved_in_zoc(false);
    shardokUnit.mutate_targeted_unit(-1);
    shardokUnit.mutate_volleys_remaining(0);
    shardokUnit.mutate_food_remaining(unit.food());
    shardokUnit.mutate_can_flee(unit.can_flee());
    shardokUnit.mutate_can_archery(unit.can_archery());
    shardokUnit.mutate_can_start_fire(unit.can_start_fire());

    if (unit.has_starting_position_index()) {
        shardokUnit.mutate_starting_position_index(unit.starting_position_index().value());
    } else {
        shardokUnit.mutate_starting_position_index(-1);
    }

    return shardokUnit;
}

}  // namespace shardok