package system.managers;

import java.io.Serializable;
import java.util.Random;

import system.battle.Coordinate;
import system.battle.Map;
import system.character.Ally;
import system.character.BaseCharacter;
import system.character.Enemy;

public class Battle implements Serializable {
	private static final long serialVersionUID = -7971141179131003381L;

	private Map map;
	
	private Ally[] allies;
	private Enemy[] enemies;
	private BaseCharacter[] roundOrder;
	private BaseCharacter activeUnit;
	
	private int activeUnitIndex = 0;
	
	/**
	 * Cria a porra da batalha com um mapa.
	 * @param map - A porra do mapa dessa batalha.
	 */
	public Battle(Map map) {
		this.map = map;
		
		allies = new Ally[2];
		enemies = new Enemy[5]; // TODO Troque pra 5
		roundOrder = new BaseCharacter[allies.length + enemies.length];
		
		// Instancia os aliados na batalha
		for (int i = 0; i < allies.length; i++) {
			allies[i] = new Ally();
		}
		
		// Instancia os inimigos na batalha
		for (int i = 0; i < enemies.length; i++) {
			enemies[i] = new Enemy();
		}
		
		// Seta as posições iniciais dos alidos
		this.map.addOccupant(allies[0], new Coordinate(0, 4));
		this.map.addOccupant(allies[1], new Coordinate(0, 5));
		
		allies[0].setName("Joãogador1");
//		allies[0].setPlayer1(true);
		
		allies[1].setName("Joségador2");
//		allies[1].setPlayer1(false);
		
		// Seta as posições iniciais dos inimigos
		this.map.addOccupant(enemies[0], new Coordinate(15, 3));
		this.map.addOccupant(enemies[1], new Coordinate(15, 4));
		this.map.addOccupant(enemies[2], new Coordinate(15, 5));
		this.map.addOccupant(enemies[3], new Coordinate(15, 6));
		this.map.addOccupant(enemies[4], new Coordinate(15, 7));
		enemies[0].setName("Inimigo 1");
		enemies[1].setName("Inimigo 2");
		enemies[2].setName("Inimigo 3");
		enemies[3].setName("Inimigo 4");
		enemies[4].setName("Inimigo 5");
		
		setRoundOrder();
		setActiveUnit();
	}
	
	public void setRoundOrder() {
		roundOrder = new BaseCharacter[]{allies[0], allies[1], enemies[0], enemies[1], enemies[2], enemies[3], enemies[4]};
//		roundOrder = new BaseCharacter[]{allies[0], allies[1], enemies[0]};	// TODO Apenas pra testes
		
//		shuffleInitiatives(roundOrder);// Foda-se essa merda
    }
	
	public void setRoundOrder(BaseCharacter[] roundOrder) {
		this.roundOrder = roundOrder;
		setActiveUnit();
	}
	
	public void passTurn() {
		activeUnitIndex++;
		
		if (activeUnitIndex == roundOrder.length) {
//			shuffleInitiatives(roundOrder);
			activeUnitIndex = 0;
		}
		
		System.out.println("PASS TURN TO "+activeUnitIndex);
		setActiveUnit();
	}
	    
	public void setActiveUnit() {
		activeUnit = roundOrder[activeUnitIndex];
	}
	
	/**
	 * USE ESTE
	 * @return
	 */
	public BaseCharacter getActiveUnitRoundOrder() {
		return roundOrder[activeUnitIndex];
	}
	
	/**
	 * Embaralha as iniciativas após todos os BaseCharacters terem agido.
	 * @param roundOrder - Os participantes da batalha
	 */
	private void shuffleInitiatives(BaseCharacter[] roundOrder) {
		Random random = new Random();
		
		for (int i = roundOrder.length - 1; i > 0; i--) {
			int index = random.nextInt(i + 1);
			
			BaseCharacter aux = roundOrder[index];
		    roundOrder[index] = roundOrder[i];
		    roundOrder[i] = aux;
		}
		
		for (int i = 0; i < roundOrder.length; i++) {
			System.out.println("ROUND ORDER: " + roundOrder[i].getName());			
		}
	}
	
	/**
	 * Inimigos mortos
	 * @return
	 */
	public boolean victory() {
		int deadCount = 0;
		
		for (int i = 0; i < enemies.length; i++) {
			if (enemies[i].isDead()) {
				deadCount++;
			}
		}
		
		System.out.println(deadCount + "/" + enemies.length);
		
		if (deadCount == enemies.length) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Aliados mortos
	 * @return
	 */
	public boolean defeat() {
		int deadCount = 0;
		
		for (int i = 0; i < allies.length; i++) {
			if (allies[i].isDead()) {
				deadCount++;
			}
		}
		
		if (deadCount == allies.length) {
			return true;
		} else {
			return false;
		}
	}

	public Map getMap() {
		return map;
	}

	public Ally[] getAllies() {
		return allies;
	}

	public Enemy[] getEnemies() {
		return enemies;
	}

	public BaseCharacter[] getRoundOrder() {
		return roundOrder;
	}

	public BaseCharacter getActiveUnit() {
		
		return activeUnit;
	}

	public int getActiveUnitIndex() {
		return activeUnitIndex;
	}

	public void setMap(Map map) {
		this.map = map;
	}

	public void setActiveUnitIndex(int activeUnitIndex) {
		this.activeUnitIndex = activeUnitIndex;
	}
}
