//
//  BattalionType.cpp
//  eagle0
//
//  Created by Dan Crosby on 11/25/14.
//  Copyright (c) 2014 none. All rights reserved.
//

#include "BattalionType.hpp"

#include <mutex>
#include <unordered_map>

#include "src/main/cpp/net/eagle0/common/MapUtils.hpp"

namespace shardok {
using std::unordered_map;

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

ActionCost actionCostForKey(const unordered_map<string, string> &map, const string &key) {
    const int pointCost = IntForKey(map, key);

    return pointCost == -1 ? IMPOSSIBLE_ACTION_COST : ActionCost::StandardActionCost(pointCost);
}

std::shared_ptr<const BattalionType> BattalionType::NewBattalionTypeFromMap(
        const std::unordered_map<std::string, std::string> &map) {
    try {
        auto *newType = new BattalionType{
                map.at("TypeName"),
                BattalionTypeId(std::stoi(map.at("TypeId"))),
                IntForKey(map, "Capacity"),
                DoubleForKey(map, "RandomnessSwing"),
                DoubleForKey(map, "MoraleSwing"),
                DoubleForKey(map, "CharismaSwing"),
                DoubleForKey(map, "BraverySwing"),
                DoubleForKey(map, "FlankDamageMultiplier"),
                DoubleForKey(map, "RearDamageMultiplier"),
                DoubleForKey(map, "ChargeMultiplier"),
                BoolForKey(map, "AllowsCasting"),
                BoolForKey(map, "AllowsStealth"),
                BoolForKey(map, "AllowsBraveWater"),
                BoolForKey(map, "AllowsMoveAfterCharge"),
                BoolForKey(map, "AdjustsMorale"),
                BoolForKey(map, "AlwaysHiddenInWater"),
                actionCostForKey(map, "CostToEnterPlains"),
                actionCostForKey(map, "CostToEnterHill"),
                actionCostForKey(map, "CostToEnterForest"),
                actionCostForKey(map, "CostToEnterMountain"),
                actionCostForKey(map, "CostToEnterSwamp"),
                actionCostForKey(map, "CostToEnterCity"),
                actionCostForKey(map, "CostToEnterOcean"),
                actionCostForKey(map, "CostToEnterIce"),
                ActionPoints(IntForKey(map, "MinimumCostToEnterBridge")),
                actionCostForKey(map, "CostToEnterCastle"),
                DoubleForKey(map, "SnowPenalty"),
                DoubleForKey(map, "ResistanceMultiplierForPlains"),
                DoubleForKey(map, "ResistanceMultiplierForHill"),
                DoubleForKey(map, "ResistanceMultiplierForForest"),
                DoubleForKey(map, "ResistanceMultiplierForMountain"),
                DoubleForKey(map, "ResistanceMultiplierForSwamp"),
                DoubleForKey(map, "ResistanceMultiplierForCity"),
                DoubleForKey(map, "ResistanceMultiplierForOcean"),
                DoubleForKey(map, "ResistanceMultiplierForCastle"),
                {DoubleForKey(map, "BaseSlashingDamage"),
                 DoubleForKey(map, "BasePuncturingDamage"),
                 DoubleForKey(map, "BaseStabbingDamage"),
                 DoubleForKey(map, "BaseCrushingDamage"),
                 DoubleForKey(map, "BaseFireDamage"),
                 DoubleForKey(map, "BaseColdDamage"),
                 DoubleForKey(map, "BaseLightningDamage"),
                 DoubleForKey(map, "BaseAessenceDamage"),
                 DoubleForKey(map, "BaseImpactDamage")},
                {DoubleForKey(map, "MaxTrainingAugmentSlashingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPuncturingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentStabbingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentCrushingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentFireDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentColdDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentLightningDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentAessenceDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentImpactDamage")},
                {DoubleForKey(map, "BasePenetratingSlashingDamage"),
                 DoubleForKey(map, "BasePenetratingPuncturingDamage"),
                 DoubleForKey(map, "BasePenetratingStabbingDamage"),
                 DoubleForKey(map, "BasePenetratingCrushingDamage"),
                 DoubleForKey(map, "BasePenetratingFireDamage"),
                 DoubleForKey(map, "BasePenetratingColdDamage"),
                 DoubleForKey(map, "BasePenetratingLightningDamage"),
                 DoubleForKey(map, "BasePenetratingAessenceDamage"),
                 DoubleForKey(map, "BasePenetratingImpactDamage")},
                {DoubleForKey(map, "MaxTrainingAugmentPenetratingSlashingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingPuncturingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingStabbingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingCrushingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingFireDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingColdDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingLightningDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingAessenceDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingImpactDamage")},
                {DoubleForKey(map, "BaseMissileSlashingDamage"),
                 DoubleForKey(map, "BaseMissilePuncturingDamage"),
                 DoubleForKey(map, "BaseMissileStabbingDamage"),
                 DoubleForKey(map, "BaseMissileCrushingDamage"),
                 DoubleForKey(map, "BaseMissileFireDamage"),
                 DoubleForKey(map, "BaseMissileColdDamage"),
                 DoubleForKey(map, "BaseMissileLightningDamage"),
                 DoubleForKey(map, "BaseMissileAessenceDamage"),
                 DoubleForKey(map, "BaseMissileImpactDamage")},
                {DoubleForKey(map, "MaxTrainingAugmentMissileSlashingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissilePuncturingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileStabbingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileCrushingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileFireDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileColdDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileLightningDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileAessenceDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentMissileImpactDamage")},
                {DoubleForKey(map, "BasePenetratingMissileSlashingDamage"),
                 DoubleForKey(map, "BasePenetratingMissilePuncturingDamage"),
                 DoubleForKey(map, "BasePenetratingMissileStabbingDamage"),
                 DoubleForKey(map, "BasePenetratingMissileCrushingDamage"),
                 DoubleForKey(map, "BasePenetratingMissileFireDamage"),
                 DoubleForKey(map, "BasePenetratingMissileColdDamage"),
                 DoubleForKey(map, "BasePenetratingMissileLightningDamage"),
                 DoubleForKey(map, "BasePenetratingMissileAessenceDamage"),
                 DoubleForKey(map, "BasePenetratingMissileImpactDamage")},
                {DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileSlashingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissilePuncturingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileStabbingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileCrushingDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileFireDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileColdDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileLightningDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileAessenceDamage"),
                 DoubleForKey(map, "MaxTrainingAugmentPenetratingMissileImpactDamage")},
                {DoubleForKey(map, "BaseSlashingResistance"),
                 DoubleForKey(map, "BasePuncturingResistance"),
                 DoubleForKey(map, "BaseStabbingResistance"),
                 DoubleForKey(map, "BaseCrushingResistance"),
                 DoubleForKey(map, "BaseFireResistance"),
                 DoubleForKey(map, "BaseColdResistance"),
                 DoubleForKey(map, "BaseLightningResistance"),
                 DoubleForKey(map, "BaseAessenceResistance"),
                 DoubleForKey(map, "BaseImpactResistance")},
                {DoubleForKey(map, "MaxArmamentAugmentSlashingResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentPuncturingResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentStabbingResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentCrushingResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentFireResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentColdResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentLightningResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentAessenceResistance"),
                 DoubleForKey(map, "MaxArmamentAugmentImpactResistance")},
                BoolForKey(map, "AlwaysArcheryCapable"),
                IntForKey(map, "BonusVolleys"),
                DoubleForKey(map, "AmbushOddsWithoutHero"),
                DoubleForKey(map, "BaseStunChanceOnCharge"),
                DoubleForKey(map, "TrainingDifferenceMultiplierForStunChanceOnCharge"),
                DoubleForKey(map, "MonthlyFoodCost")};

        return std::shared_ptr<const BattalionType>(newType);
    } catch (const std::out_of_range &e) {
        printf("Failed to parse file map; caught exception %s\n", e.what());
        return nullptr;
    }
}
}  // namespace shardok
