package com.bernard.greposimu.model;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import com.bernard.greposimu.model.game.units.Hero;
import com.bernard.greposimu.model.game.units.Unit;

public class DefContext {
	
	// UNITS
	// Units unrelated to the attacker
	Map<Unit, Integer> otherUnits;
	// Units owned by allies of the attacker
	Map<Unit, Integer> alliedUnits;
	// Units owned by the attacher
	Map<Unit, Integer> selfUnits;
	
	// HEROS
	Hero hero = null;
	int heroLevel = 0;
	
	// BUILDINGS
	int wallLevel = 0;
	boolean hasTower=false;
	
	// RESEARCHES
	boolean divineSelection= false, phalanx = false, ram=false;
	
	// COUNSELLORS
	boolean commander= false;
	boolean priest = false;
	boolean captain = false;
	
	// EFFECTS
	// PC x2
	boolean acumen = false;
	// PC x4
	boolean divineSenses= false;
	// Attq +10%, Def -10%
	boolean myrmidionAttack= false;
	// Remparts +1, Milice+5/farm (level max 25)
	boolean trojanDefense= false;
	// Def +5%
	boolean defenseBoost= false;
	// Def -10%
	boolean defensePenalty= false;
	// Def +5%
	boolean longtermDefenseBoost= false;
	// PC +50%
	boolean assassinsAcumen= false;
	// Def +5%
	boolean rareDefenseBoost= false;
	// Def +10%
	boolean epicDefenseBoost= false;
	// +50% PC
	boolean missionsPower4= false;
	// PC+50% (sauf BC, transport)
	boolean divineBattleStrategyRare= false;
	// PC+100% (sauf BC, transport)
	boolean divineBattleStrategyEpic= false;
	// PC+50% against naval (sauf BC,transports)
	boolean navalBattleStrategyRare= false;
	// PC+100% against naval (sauf BC, transport)
	boolean navalBattleStrategyEpic= false;
	// PC+50% against terrestres
	boolean landBattleStrategyRare= false;
	// PC+100% against terrestre
	boolean landBattleStrategyEpic= false;
	// Def -10%
	boolean narcissism= false;
	// PC+10%*level
	int olympicSensesGrepolympiaSummerLevel = 0;
	// Def +5%*level
	int olympicTorchGrepolympiaSummerLevel = 0;
	// Df +0.7%*level
	int soteriasShrineLevel = 0;
	
	// BONUSES
	boolean nightBonus = false;

	public DefContext(Map<Unit, Integer> units, Hero hero, int heroLevel, int wallLevel, boolean hasTower,
			Set<String> powers, int soteriasShrinePowerLevel, int olympicTorchGrepolympiaSummerLevel, int olympicSensesGrepolympiaSummerLevel,
			Set<String> researches, Set<String> counsellors, boolean nightBonus) {
		this(units,Map.of(),Map.of(),hero,heroLevel,wallLevel,hasTower,powers,soteriasShrinePowerLevel,olympicTorchGrepolympiaSummerLevel,olympicSensesGrepolympiaSummerLevel,researches,counsellors,nightBonus);
	}
	
	public DefContext(Map<Unit, Integer> otherUnits, Map<Unit, Integer> alliedUnits, Map<Unit, Integer> selfUnits, Hero hero, int heroLevel, int wallLevel, boolean hasTower,
			Set<String> powers, int soteriasShrinePowerLevel, int olympicTorchGrepolympiaSummerLevel, int olympicSensesGrepolympiaSummerLevel, Set<String> researches, Set<String> counsellors, boolean nightBonus) {
		this.otherUnits = otherUnits;
		this.alliedUnits = alliedUnits;
		this.selfUnits = selfUnits;
		this.hero = hero;
		this.heroLevel = heroLevel;
		this.wallLevel = wallLevel;
		this.hasTower = hasTower;
		if(powers.contains("acumen"))this.acumen = true;
		if(powers.contains("divine_senses"))this.divineSenses = true;
		if(powers.contains("myrmidion_attack"))this.myrmidionAttack = true;
		if(powers.contains("trojan_defense"))this.trojanDefense = true;
		if(powers.contains("defense_boost"))this.defenseBoost = true;
		if(powers.contains("defense_penalty"))this.defensePenalty = true;
		if(powers.contains("longterm_defense_boost"))this.longtermDefenseBoost = true;
		if(powers.contains("assassins_acumen"))this.assassinsAcumen = true;
		if(powers.contains("rare_defense_boost"))this.rareDefenseBoost = true;
		if(powers.contains("epic_defense_boost"))this.epicDefenseBoost = true;
		if(powers.contains("olympic_torch"))this.olympicTorchGrepolympiaSummerLevel = olympicTorchGrepolympiaSummerLevel;
		if(powers.contains("olympic_senses"))this.olympicSensesGrepolympiaSummerLevel = olympicSensesGrepolympiaSummerLevel;
		if(powers.contains("missions_power_4"))this.missionsPower4 = true;
		if(powers.contains("divine_battle_strategy_rare"))this.divineBattleStrategyRare = true;
		if(powers.contains("divine_battle_strategy_epic"))this.divineBattleStrategyEpic = true;
		if(powers.contains("naval_battle_strategy_rare"))this.navalBattleStrategyRare = true;
		if(powers.contains("naval_battle_strategy_epic"))this.navalBattleStrategyEpic = true;
		if(powers.contains("land_battle_strategy_rare"))this.landBattleStrategyRare = true;
		if(powers.contains("land_battle_strategy_epic"))this.landBattleStrategyEpic = true;
		if(powers.contains("soterias_shrine"))this.soteriasShrineLevel = soteriasShrinePowerLevel;
		if(powers.contains("narcissism"))this.narcissism = true;
		if(researches.contains("divine_selection"))this.divineSelection = true;
		if(researches.contains("phalanx"))this.phalanx = true;
		if(researches.contains("ram"))this.ram = true;
		if(counsellors.contains("commander"))this.commander = true;
		if(counsellors.contains("priest"))this.priest = true;
		if(counsellors.contains("captain"))this.captain = true;
		this.nightBonus = nightBonus;
	}
	
	public int unitCount(Unit u) {
		return 
			Optional.ofNullable(otherUnits.getOrDefault(u,0)).orElse(0) +
			Optional.ofNullable(alliedUnits.getOrDefault(u,0)).orElse(0) +
			Optional.ofNullable(selfUnits.getOrDefault(u,0)).orElse(0);
	}
	public Hero getHero() {
		return hero;
	}
	public int getHeroLevel() {
		return heroLevel;
	}
	public int getWallLevel() {
		return wallLevel;
	}
	public boolean hasTower() {
		return hasTower;
	}
	public boolean isNightBonus() {
		return nightBonus;
	}
	
	public boolean hasDivineSelection() {
		return divineSelection;
	}

	public boolean hasPhalanx() {
		return phalanx;
	}

	public boolean hasRam() {
		return ram;
	}

	public boolean hasCommander() {
		return commander;
	}

	public boolean hasPriest() {
		return priest;
	}

	public boolean hasCaptain() {
		return captain;
	}

	public boolean hasAcumen() {
		return acumen;
	}

	public boolean hasDivineSenses() {
		return divineSenses;
	}

	public boolean hasMyrmidionAttack() {
		return myrmidionAttack;
	}

	public boolean hasTrojanDefense() {
		return trojanDefense;
	}

	public boolean hasDefenseBoost() {
		return defenseBoost;
	}

	public boolean hasDefensePenalty() {
		return defensePenalty;
	}

	public boolean hasLongtermDefenseBoost() {
		return longtermDefenseBoost;
	}

	public boolean hasAssassinsAcumen() {
		return assassinsAcumen;
	}

	public boolean hasRareDefenseBoost() {
		return rareDefenseBoost;
	}

	public boolean hasEpicDefenseBoost() {
		return epicDefenseBoost;
	}

	public boolean hasMhassionsPower4() {
		return missionsPower4;
	}

	public boolean hasDivineBattleStrategyRare() {
		return divineBattleStrategyRare;
	}

	public boolean hasDivineBattleStrategyEpic() {
		return divineBattleStrategyEpic;
	}

	public boolean hasNavalBattleStrategyRare() {
		return navalBattleStrategyRare;
	}

	public boolean hasNavalBattleStrategyEpic() {
		return navalBattleStrategyEpic;
	}

	public boolean hasLandBattleStrategyRare() {
		return landBattleStrategyRare;
	}

	public boolean hasLandBattleStrategyEpic() {
		return landBattleStrategyEpic;
	}

	public int getOlympicSensesGrepolympiaSummerLevel() {
		return olympicSensesGrepolympiaSummerLevel;
	}

	public int getOlympicTorchGrepolympiaSummerLevel() {
		return olympicTorchGrepolympiaSummerLevel;
	}

	public int getSoteriasShrineLevel() {
		return soteriasShrineLevel;
	}
	
	public boolean hasNarcissism() {
		return narcissism;
	}
	
	public static final List<String> POWERS = List.of("acumen", "divine_senses", "myrmidion_attack", "trojan_defense",
			"defense_boost", "defense_penalty", "longterm_defense_boost", "assassins_acumen", "rare_defense_boost",
			"epic_defense_boost", "olympic_torch", "olympic_senses", "missions_power_4", "divine_battle_strategy_rare",
			"divine_battle_strategy_epic", "naval_battle_strategy_rare", "naval_battle_strategy_epic",
			"land_battle_strategy_rare", "land_battle_strategy_epic", "soterias_shrine", "narcissism");
	public static final List<String> RESEARCHES = List.of("divine_selection","phalanx","ram");
	public static final List<String> COUNSELLORS = List.of("priest","commander","captain");
}
