package com.bernard.greposimu.model.game;

import java.util.Arrays;
import java.util.Collections;
import java.util.Set;

import com.bernard.greposimu.Utils;
import com.bernard.greposimu.model.game.powers.Power;
import com.bernard.greposimu.model.game.researches.Research;
import com.bernard.greposimu.model.game.units.Hero;
import com.bernard.greposimu.model.game.units.Unit;

public class GameConfig {
	
	Set<God> gods;
	
	// Non-hero units
	Set<Unit> units;
	
	Set<Hero> heroes;
	
	Set<Research> researches;
	
	Set<Power> powers;
	
	
	
	public GameConfig(Set<God> gods, Set<Unit> units, Set<Hero> heroes, Set<Research> researches, Set<Power> powers) {
		this.gods = gods;
		this.units = units;
		this.heroes = heroes;
		this.researches = researches;
		this.powers = powers;
	}
	
	public Set<God> getGods() {
		return gods;
	}

	public Set<Unit> getUnits() {
		return Collections.unmodifiableSet(this.units);
	}
	
	public Unit getUnit(String id) {
		return Utils.getIdentified(this.units, id);
	}
	
	public Set<Hero> getHeroes() {
		return Collections.unmodifiableSet(this.heroes);
	}
	public Hero getHero(String id) {
		return Utils.getIdentified(this.heroes, id);
	}
	
	public Set<Research> getResearches() {
		return Collections.unmodifiableSet(this.researches);
	}
	public Research getResearch(String id) {
		return Utils.getIdentified(this.researches, id);
	}

	public Building getBuilding(String bid) {
		return Arrays.stream(Building.values()).filter(b -> b.id.equals(bid)).findAny().orElse(null);
	}

	public God getGod(String god) {
		return Utils.getIdentified(this.gods, god);
	}

	public Set<Building> getBuildings() {
		return Set.of(Building.values());
	}

	@SuppressWarnings("unchecked")
	public <T extends Identified> T getIdentified(Class<T> clazz, String id) {
		if(Unit.class.isAssignableFrom(clazz))
			return (T)this.getUnit(id);
		if(Hero.class.isAssignableFrom(clazz))
			return (T)this.getHero(id);
		if(Research.class.isAssignableFrom(clazz))
			return (T)this.getResearch(id);
		if(God.class.isAssignableFrom(clazz))
			return (T)this.getGod(id);
		if(Building.class.isAssignableFrom(clazz))
			return (T)this.getBuilding(id);
		throw new UnsupportedOperationException("Cannot get identified object of class "+clazz.getName());
	}
	
	public static int getTotalPop(int farmLevel, boolean thermal, boolean charrue, boolean pygmallion, int bonus) {
		int tot = Building.getFarmPopulation(farmLevel);
		if(thermal)tot = (int)Math.floor(tot*1.1);
		if(charrue)tot += 200;
		if(pygmallion)tot += 5*farmLevel;
		tot += bonus;
		return tot;
	}
	
}
