package games.league;

import ec.simple.SimpleFitness;
import ec.vector.DoubleVectorIndividual;
import games.Player;
import games.scenarios.GameScenario;
import games.scenarios.SimpleTwoPlayersGameScenario;

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;

import cecj.app.othello.OthelloBoard;
import cecj.app.othello.OthelloGame;
import cecj.app.othello.OthelloPlayer;


public class League {
	
	private List<String> names;
	private List<List<Player>> teams;
	
	private int[] score;
	private int[] wins;
	private int[] draws;
	private int[] losts;
	
	private Player bestPlayer;
	private int bestPlayerScore;
	private String bestPlayerTeam;
	
	public League() {
		teams = new ArrayList<List<Player>>();
		names = new ArrayList<String>();
	}
	
	public void play() {
		score = new int[teams.size()];
		wins = new int[teams.size()];
		draws = new int[teams.size()];
		losts = new int[teams.size()];
		GameScenario scenario;
		OthelloGame game = new OthelloGame(new OthelloBoard());
		
		bestPlayer = null;
		bestPlayerTeam = null;
		bestPlayerScore = 0;
		
		for (int team = 0; team < teams.size(); team++) {
			for (Player player : teams.get(team)) {
				int playerScore = 0;

				for (int opponentTeam = 0; opponentTeam < teams.size(); opponentTeam++) {
					if (team == opponentTeam) continue;
				
					for (Player opponent : teams.get(opponentTeam)) {
						scenario = new SimpleTwoPlayersGameScenario(new Player[] { player, opponent });						
						game.reset();
						int result = scenario.play(game);
						score[team] += points(result);
						playerScore += points(result);
						if (result > 0) wins[team]++;
						if (result == 0) draws[team]++;
						if (result < 0) losts[team]++;
						
						scenario = new SimpleTwoPlayersGameScenario(new Player[] { opponent, player });
						game.reset();
						result = -scenario.play(game);
						score[team] += points(result);
						playerScore += points(result);
						if (result > 0) wins[team]++;
						if (result == 0) draws[team]++;
						if (result < 0) losts[team]++;
					}
				}
				
				if (playerScore > bestPlayerScore) {
					bestPlayerScore = playerScore;
					bestPlayer = player;
					bestPlayerTeam = names.get(team);
				}
			}
		}
	}

	private static int points(int result) {
		if (result > 0) {
			return 3;
		} else if (result == 0){
			return 1;
		} else {
			return 0;
		}
	}

	public void printTable() {
		for (int team = 0; team < teams.size(); team++) {
			System.out.println(names.get(team) + " : " + score[team] + "\t\t wins = " + wins[team] + " draws = " + draws[team] + " losts = " + losts[team]);
		}
	}
	
	private void addTeam(String name, String filename) {
		DoubleVectorIndividual ind = new DoubleVectorIndividual();
		ind.fitness = new SimpleFitness();
		ind.genome = new double[64];
				
		try {
			List<Player> team = new ArrayList<Player>();
			LineNumberReader reader = new LineNumberReader(new FileReader(filename));
			Integer.parseInt(reader.readLine());
			for (int i = 0; i < 20; i++) {
				ind.readIndividual(null, reader);
				team.add(new OthelloPlayer(ind.genome));
			}
			teams.add(team);
			names.add(name);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void printBestPlayer() {
		System.out.println("\n Best player comes from team " + bestPlayerTeam + " and its score = " + bestPlayerScore);
		
		double[] wpc = ((OthelloPlayer)bestPlayer).getWPC();
		for (int i = 0; i < 64; i++) {
			if (i % 8 == 0) {
				System.out.println(""); 
			} else {
				System.out.print(" "); 
			}
			System.out.print(Math.round(wpc[i] * 100) / 100.);
		}
	}
	
	public static void main(String[] args) {
		League league = new League();
		league.addTeam("CEL", "EXP_CEL_best_players");
		league.addTeam("CEL + HoF", "EXP5v0_best_players");
		league.addTeam("TDL", "EXP3_best_players");
		league.addTeam("CEL + TDL", "EXP4_best_players");
		league.addTeam("CEL + TDL + HoF", "EXP5_best_players");
		//league.addTeam("CEL + TDL(0) + HoF", "EXP5v0_best_players");
		//league.addTeam("CEL + TDL(1)(rand) + HoF", "EXP5v1rand_best_players");
		//league.addTeam("CEL + TDL(2) + HoF", "EXP5v2_best_players");
		//league.addTeam("CEL + TDL(5) + HoF", "EXP5v5_best_players");
		//league.addTeam("CEL + TDL(10) + HoF", "EXP5v10_best_players");
		//league.addTeam("CEL + TDL(50) + HoF", "EXP5v50_best_players");
		
		league.play();
		league.printTable();
		league.printBestPlayer();
	}

}