import java.util.ArrayList;
import java.util.List;
public class Partida {
    private int turno; // Puede que turno tubiera que ser de tipo Jugador
    // O una clase Turno que encapsulara que es
    private List<Jugador> jugadores;
    private final Pila pila;
    private final Mesa mesa;
    private final boolean omniconsciencia;
    private int pasadas; // Veces consecutivas que un jugador pasa
    // si pasadas == jugadores.size() se acaba el juego. 
    public static final int COLOR_PILA = -1;
    public static final int COLOR_MESA = 0;
    public static final int COLOR_JUGADORES = 1;
    public static final int COLOR_TURNO = 4;
    public static final int COLOR_JUGADA = 2;
    public static final int MIN_JUGADORES = 2;
    public static final int MAX_JUGADORES = 4;
    public Partida() {
        int numJugadores = Pregunta.numEnRango("¿Numero de jugadores?",
                MIN_JUGADORES, MAX_JUGADORES);
        boolean hayUnHumano = Pregunta.siONo("¿Un jugador humano?");
        if (!hayUnHumano) {
            omniconsciencia = true;
        } else {
            omniconsciencia = Pregunta.siONo("¿Quieres omniconsciencia?");
        }
        Azar.inicializar();
        pila = new Pila();
        mesa = new Mesa();
        initJugadores(numJugadores, hayUnHumano);
        pasadas = 0;
        realizarPrimeraTirada();
    }
    private void initJugadores(int numJugadores, boolean hayUnHumano) {
        int tipo;
        this.jugadores = new ArrayList<>();
        for (int j = 0; j < numJugadores; j++) {
            if (j == 0 && hayUnHumano) {
                tipo = Jugador.HUMANO;
            } else {
                tipo = Jugador.ROBOT;
            }
            Jugador jugador = new Jugador(tipo, mesa);
            for (int i = 0; i <= Ficha.NUM_MAS_ALTO; i++) {
                jugador.pillaFicha(pila.cogerFichaDeLaPila());
            }
            jugadores.add(jugador);
        }
    }
    private Jugador getJugadorAlAzar() {
        return jugadores.get(Azar.numeroAlAzar(jugadores.size()));
    }
    private void realizarPrimeraTirada() {
        Jugador jugador = null;
        Ficha dobleMasAlto = null, fichaATirar, ficha;
        for (Jugador j : jugadores) {
            ficha = j.getDobleMasAlto();
            if (ficha != null) {
                if ((dobleMasAlto == null)
                        || (ficha.peso() > dobleMasAlto.peso())) {
                    dobleMasAlto = ficha;
                    jugador = j;
                }
            }
        }
        if (dobleMasAlto == null) {
            jugador = getJugadorAlAzar();
            fichaATirar = jugador.getFichaAlAzar();
        } else {
            fichaATirar = dobleMasAlto;
        }
        jugador.tiraFicha(fichaATirar);
        mesa.tirarPrimeraFicha(fichaATirar);
        turno = jugadores.indexOf(jugador);
    }
    public void pasarTurno() {
        turno = (turno + 1) % jugadores.size();
    }
    public void jugadorRealizaTirada(Jugador jugador, Tirada tirada) {
        jugador.tiraFicha(tirada.getFicha());
        if (tirada.getExtremoMesa().equals(ExtremoMesa.IZQUIERDO)) {
            mesa.tirarPorLaIzquierda(tirada.getFicha());
        } else if (tirada.getExtremoMesa().equals(ExtremoMesa.DERECHO)) {
            mesa.tirarPorLaDerecha(tirada.getFicha());
        } else {
            System.out.println("ERR: Partida.jugadorRealizaTirada");
        }
    }
    public void realizarJugada() {
        Jugador jugadorEnTurno = jugadores.get(turno);
        boolean isHuman = jugadorEnTurno.isHuman();
        ArrayList<Tirada> tiradas;
        do {
            tiradas = jugadorEnTurno.posiblesTiradas();
            if (tiradas.isEmpty() && !pila.estaVacia()) {
                System.out.print(Colores.color(COLOR_JUGADA));
                System.out.print("Va a la pila! Pilla un ");
                Ficha ficha = pila.cogerFichaDeLaPila();
                jugadorEnTurno.pillaFicha(ficha);
                if (isHuman || omniconsciencia) {
                    System.out.print(ficha);
                } else {
                    System.out.print(Ficha.OCULTA);
                }
                System.out.println(" ;-P");
            } else if (isHuman) {
                int i = 0;
                for (Tirada t : tiradas) {
                    System.out.print(Colores.color(COLOR_JUGADA));
                    System.out.print("[" + i++ + "]" + t + " ");
                }
            }
        } while (tiradas.isEmpty() && !pila.estaVacia());
        if (tiradas.isEmpty()) {
            pasadas++;
            System.out.print(Colores.color(COLOR_JUGADA));
            System.out.println("Pasa! ;-P");
        } else {
            pasadas = 0;
            jugadorRealizaTirada(jugadorEnTurno,
                    jugadorEnTurno.preguntarTiradaAJugador(tiradas));
        }
        Colores.resetColor();
    }
    public boolean seHaAcabado() {
        if (jugadores.get(turno).getNumFichas() == 0) {
            System.out.print(Colores.color(COLOR_JUGADA));
            System.out.println("\n===>>> Ha ganado el J" + turno + "! :-)");
            return true;
        } else {
            if (pasadas == jugadores.size()) {
                System.out.print(Colores.color(COLOR_JUGADA));
                System.out.println("\n===>>> Juego bloqueado.");
                return true;
            }
            return false;
        }
    }
    private static String toStringFichasOcultas(int numFichasOcultas) {
        String s = "";
        for (int i = 0; i < numFichasOcultas; i++) {
            s += Ficha.OCULTA;
        }
        return s;
    }
    @Override
    public String toString() {
        String s = "";
        s += "\n" + Colores.color(COLOR_PILA) + "Pila:\t";
        if (omniconsciencia) {
            s += pila;
        } else {
            s += toStringFichasOcultas(pila.getNumFichas());
        }
        s += "\n" + Colores.color(COLOR_MESA) + "Mesa:\t" + mesa;
        for (int i = 0; i < jugadores.size(); i++) {
            Jugador jugador = jugadores.get(i);
            s += "\n" + Colores.color(COLOR_JUGADORES) + "J" + i + ":\t";
            if (omniconsciencia || jugador.isHuman()) {
                s += jugador;
            } else {
                s += toStringFichasOcultas(jugador.getNumFichas());
            }
        }
        s += "\n" + Colores.color(COLOR_TURNO) + "Turno: " + turno;
        s += Colores.resetColor();
        return s;
    }
}
