//
//  MeleeUtils.hpp
//  eagle0_engine
//
//  Created by Dan Crosby on 1/1/19.
//  Copyright © 2019 none. All rights reserved.
//

#ifndef MeleeUtils_hpp
#define MeleeUtils_hpp

#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
#include "src/main/protobuf/net/eagle0/shardok/common/action_type.pb.h"
#include "src/main/protobuf/net/eagle0/shardok/storage/action_result.pb.h"

namespace shardok {

using net::eagle0::shardok::common::ActionType;
using net::eagle0::shardok::storage::ActionResult;
using std::vector;

using BattalionFb = net::eagle0::shardok::storage::fb::Battalion;
using HeroFb = net::eagle0::shardok::storage::fb::Hero;

struct MeleeResultFb {
    Unit attackerAfter;
    Unit defenderAfter;
};

class CombatUtils {
private:
    const SettingsGetter settings;

public:
    explicit CombatUtils(const SettingsGetter &getter) : settings(getter) {}

    static auto CalculateHeroDamageGiven(
            const HeroFb &hero,
            double percentileRoll,
            const SettingsGetter &settings,
            bool isDuel = false) -> CombatDamage;

    static auto CalculateBattalionDamageGiven(
            const BattalionFb &battalion,
            const std::optional<double> &cmdrCharisma,
            const std::optional<double> &cmdrBravery,
            double percentileRoll,
            const SettingsGetter &settings) -> CombatDamage;

    static auto CalculateUnitDamageGiven(
            const Unit *unit,
            double heroRoll,
            double battalionRoll,
            const SettingsGetter &settings) -> CombatDamage;

    static auto CalculateUnitChargeDamageGiven(
            const Unit *unit,
            double heroRoll,
            double battalionRoll,
            const SettingsGetter &settings) -> CombatDamage;

    static auto CalculateUnitArcheryDamageGiven(
            const Unit &unit,
            double battalionRoll,
            const SettingsGetter &settings) -> CombatDamage;

    static auto InternalPerformMelee(
            const ActionCost cost,
            const Unit *att,
            const Unit *def,
            const Terrain defenderTerrain,
            AttackOrientation orientation,
            double attackerRoll,
            double defenderRoll,
            bool isCharge,
            bool isAmbush,
            const SettingsGetter &settings) -> MeleeResultFb;

    static auto MeleeActionResult(const MeleeResultFb &results) -> ActionResult;
    static auto MeleeAmbushResult(const MeleeResultFb &results) -> ActionResult;
    static auto ChargeResult(const MeleeResultFb &results) -> ActionResult;

    static auto DefenderTerrainAllowsAmbush(const Terrain &terrain) -> bool {
        return !terrain.modifier().castle().present();
    }
};
}  // namespace shardok

#endif /* MeleeUtils_hpp */
