package game.goals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import game.Game;
import game.Goal;
import game.Player;
import game.map.Castle;

/**
 * Derjenige Spieler gewinnt, der als erstes jeweils 10 Truppen auf 5 Burgen bringt
 * @author dennis
 *
 */
public class PopulationGoal extends Goal {

	private int populationNeeded = 10;
	private int castlesNeeded = 5;
	
	boolean isDraw;
	
	/**
	 * Creates a new population goal
	 */
	public PopulationGoal() {
		super("Bevölkerung", "Derjenige Spieler gewinnt, der als erstes jeweils 10 Truppen auf 5 Burgen bringt");
		isDraw = false;
	}
	
    @Override
    public boolean isCompleted() {
        // Call getWinner to set isDraw
		getWinner();
		return isDraw || this.getWinner() != null;
    }
    
    @Override
    public Player getWinner() {
        Game game = this.getGame();
        
        if(game.getRound() < 2)
            return null;

       
        // Ansonsten: BevÃ¶lkerung zÃ¤hlen
        
        int numberOfHighPopulationCastles = 0;
        
        List<Player> highPopulationPlayers = new ArrayList<>();
        
        for (Player p : game.getPlayers()) {
        	for(Castle c : p.getCastles(game)) {
        		if(c.getTroopCount() >= populationNeeded) {
        			numberOfHighPopulationCastles++;
        		}
        	}
        	
        	if(numberOfHighPopulationCastles >= castlesNeeded) {
        		highPopulationPlayers.add(p);
        	}
        	
        	numberOfHighPopulationCastles = 0;
        	
        }
        
        if(highPopulationPlayers.size() == 1) {
        	return highPopulationPlayers.get(0);
        } else if(highPopulationPlayers.size() > 1) {
        	// Spieler mit meisten regionen gewinnt
        	
        	Comparator<Player> comp = new Comparator<Player>() {

				@Override
				public int compare(Player o1, Player o2) {
					return Integer.compare(o1.getNumRegions(game), o2.getNumRegions(game));
				}
        		
        	};
        	
        	Collections.sort(highPopulationPlayers, comp);
        	// Edge Case: Mehrere Spieler haben auch die gleiche Anzahl an Regionen. Dann gibt es ein Draw.
        	if(highPopulationPlayers.get(0).getNumRegions(game) == highPopulationPlayers.get(1).getNumRegions(game)) {
        		isDraw = true;
        		return null;
        	}
        	return Collections.max(highPopulationPlayers, comp);      	
        }
        
        // Ansonsten... gewinnt noch kein spieler.
        return null;
        
    }
    
    
    @Override
    public boolean hasLost(Player player) {
        if(getGame().getRound() < 2)
            return false;

        return player.getNumRegions(getGame()) == 0 || (this.isCompleted() && !player.equals(this.getWinner()));
    }
    
}
