package modelo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import com.sun.xml.internal.bind.v2.runtime.reflect.ListIterator;
import modelo.Player.Colors;
import cards.Biblioteca;
import cards.Card;
import cards.Cripta;
import cards.Features;
import cards.Scriptorium;
import cards.Features.*;
import cards.Monje;
import tablero.Square;
import tablero.Tablero;
//import vista.ScriptoriumModel;
import vista.VistaConsola;
public class Partida {
private Tablero tablero;
private List<Player> playerList;
private List<UpdateListener> listeners;
private Monje asesino;
private Set<Monje> cartasMonjeMesa;
private int turno;
boolean empezada = false;
private final int MAX_MOVES = 2;
private Misas misa;
Misas currentMisa;
private Biblioteca biblioteca = new Biblioteca(null);
private Scriptorium scriptorium= new Scriptorium(null);
private Cripta cripta= new Cripta(null);
public List<BibliotecaModel> getBiblioCards()
{
return biblioteca.getLibraryCards();
}
public List<ScriptoriumModel> getScriptoriumCards() {
return scriptorium.getScriptoriumCards();
}
public List<String> getCriptaCards()
{
return cripta.getCriptaCards();
}
public Partida() {
playerList = new ArrayList<Player>();
tablero = new Tablero();
listeners = new ArrayList<UpdateListener>();
turno = 0;
misa = Misas.Maitines;
}
public int getCardsForMisa() {
return misa.getCartasPorMisa();
}
private void setNextMisa() {
Misas a[] = Misas.values();
int n = 0;
while (a[n] != misa)
n++;
misa = a[(n + 1) % a.length];
}
public Misas getMisa() {
return misa;
}
public void inicializarPartida() {
List<Monje> monjeList = new ArrayList<Monje>();
if (crearMonjes(monjeList)) {
reparteHojasSospechoso(monjeList);
reparteCartasMonje(monjeList);
for (Player j : playerList)
j.marcarSospechosos();
moverACasillaInicial();
}
}
public void moverACasillaInicial() {
for (Player j : playerList){
if(j.getUbication()!=null)j.getUbication().removePlayer(j);
j.setUbicacion(getSquare(1));
}
}
public void setEmpezada() {
empezada = true;
notificarPartidaEmpezada();
}
// TODO: RECORDAR CAMBIAR for(Player j:playerList){ notifyMisa(j);} a modelo
// de RED
public void turnos() {
boolean terminada = false;
while (!terminada) {
turnInc();
for (Player j : playerList)
notificarTurnoJugador(j); // turno de cada jugador
for (Player j : playerList)
j.reset(); // se resetea el booleano de cada jugador para nuevos
// movimientos
if (turno % 4 == 0) {
moverACasillaInicial();
// 1)NOTIFICAR A LA VISTA FUNCION CON JUGADOR PARA CAMBIAR SUS
// CARTAS
for (Player j : playerList)
notifyMisa(j);
this.setNextMisa();
}
if (getSquare(18).getPlayerList().size() >= 1)
terminada = true; // el jugador que llegue a la capilla gana
}
}
private void notifyMisa(Player j) {
for (UpdateListener listener : listeners) {
listener.cardsExchangeMode(j);
}
}
public int askQuestion(Player j, int hand, List<Features> questions) {
return j.answer(hand, questions);
}
public boolean askQuestion(Player j1, Player j2, int where, String name) { // j1
// pregunta
// j2
// responde
if (j2.answer(where, name)) {
j1.marcarSospechoso(name);
return true;
} else
return false;
}
public Set<Square> getReachableSquares(Player j) {
Set<Square> validas = null; // validas a 1 casilla de distancia
if (j != null) {
Square casillaInicial = getPlayerLocation(j);
Set<Square> validas2 = new TreeSet<Square>(); // validas a 2
// casillas de
// distancia
validas = tablero.squaresConnectedTo(casillaInicial);
for (Square square : validas) {
validas2.addAll(tablero.squaresConnectedTo(square));
}
validas.addAll(validas2);
validas.remove(casillaInicial);
}
return validas;
}
private void notificarMovements(Player j, Set<Square> casillasValidas) {
for (UpdateListener listener : listeners) {
listener.movements(j, casillasValidas);
}
}
private boolean crearMonjes(List<Monje> listaCartas) {
List<java.util.Hashtable> list = LectorFicheros.read();
if (list != null) {
for (java.util.Hashtable tabla : list) {
List<Features> characteriticsList = new ArrayList<Features>();
characteriticsList.add(Titulo.valueOf((String) tabla
.get("categoria")));
characteriticsList.add(Cabeza.valueOf((String) tabla
.get("cabeza")));
characteriticsList.add(Orden.valueOf((String) tabla
.get("orden")));
characteriticsList.add(Cuerpo.valueOf((String) tabla
.get("cuerpo")));
characteriticsList.add(VelloFacial.valueOf((String) tabla
.get("peloCara")));
Monje monje = new Monje((String) tabla.get("nombre"),
characteriticsList, (String) tabla.get("imagen"));
listaCartas.add(monje);
}
return true;
} else
return false;
}
private void reparteMonks(List<Monje> listaMonjes, int mesa, int player) {
cartasMonjeMesa = new HashSet<Monje>();
for (int i = 0; i < mesa; i++)
cartasMonjeMesa.add((Monje) listaMonjes.remove(0));
List<Player> players = getPlayerList();
for (Player j : players) {
Set<Monje> cartasMonjeJugador = new HashSet<Monje>();
for (int i = 0; i < player; i++)
cartasMonjeJugador.add((Monje) listaMonjes.remove(0));
j.setCartasMonje(cartasMonjeJugador);
}
}
private boolean reparteCartasMonje(List<Monje> listaMonjes) {
if (listaMonjes.size() == 24) {
Collections.shuffle(listaMonjes); // Barajar las cartas de Monje
switch (getPlayerList().size()) {
case 1:
reparteMonks(listaMonjes, 13, 10);
break;
case 2:
reparteMonks(listaMonjes, 3, 10);
break;
case 3:
reparteMonks(listaMonjes, 5, 6);
break;
case 4:
reparteMonks(listaMonjes, 3, 5);
break;
case 5:
reparteMonks(listaMonjes, 3, 4);
break;
case 6:
reparteMonks(listaMonjes, 5, 3);
}// end switch;
asesino = listaMonjes.remove(0);
return true;
} else
return false;
}
public void reparteHojasSospechoso(List<Monje> listaMonjes) {
Set<Sospechoso> sospechosos = new TreeSet<Sospechoso>();
for (Monje monje : listaMonjes) {
sospechosos.add(new Sospechoso(monje));
}
for (Sospechoso s : sospechosos) {
s.setId();
}
for (Player j : playerList) {
j.setHojaDeSospechosos(new TreeSet(sospechosos));
}
}
public void turnInc() {
turno++;
}
public void setPlayerTurn(Player j, boolean turno) {
j.reset();
if (turno)
notificarTurnoJugador(j);
}
public int getTurno() {
// return turno;
return turno;
}
public void addUpdateListener(UpdateListener listener) {
listeners.add(listener);
}
public List<Player> getPlayerList() {
return playerList;
}
public List<Square> getSquareList() {
return tablero.getSquareList();
}
public Square getSquare(int squareNumber) {
Square casilla = null;
for (Square c : tablero.getSquareList()) {
if (squareNumber == c.getNumCasilla())
casilla = c;
}
return casilla;
}
public Square getSquare(String nombreCasilla) {
Square casilla = null;
for (Square c : tablero.getSquareList()) {
if (nombreCasilla == c.getSquareName())
casilla = c;
}
return casilla;
}
public boolean playerMove(Player j, Square c) {
if (j != null && c != null && tablero.isSquare(c)) {
Set<Square> validas = getReachableSquares(j);
if (validas.contains(c)) {
Square antigua = j.getUbication();
if (antigua != null)
antigua.removePlayer(j);
j.move(c);
c.addPlayer(j);
notificarUbicacionActualizada(j);
if (c.getPlayerList().size() > 1)
notifyTwoPlayersHere(j, c);
return true;
} else
return false;
} else
return false;
}
private void notificarUbicacionActualizada(Player j) {
for (UpdateListener listener : listeners) {
listener.ubicacionActualizada(j);
}
}
private void notifyTwoPlayersHere(Player j, Square c) {
for (UpdateListener listener : listeners) {
listener.twoPlayersHere(j, c);
}
}
private void notificarPartidaEmpezada() {
for (UpdateListener listener : listeners) {
listener.partidaEmpezada();
}
}
private void notificarNuevoJugador(Player j) {
for (UpdateListener listener : listeners) {
listener.newPlayer(j);
}
}
private void notificarTurnoJugador(Player j) {
for (UpdateListener listener : listeners) {
listener.playerTurn(j);
}
}
public Square getPlayerLocation(Player j) {
return j.getUbication();
}
public void addPlayer(String nombre, Colors color) {
Player player = new Player(nombre, color);
playerList.add(player);
notificarNuevoJugador(player);
}
public Player getPlayer(int numero) {
Player player = null;
for (Player j : playerList)
if (numero == j.getNumero())
player = j;
return player;
}
public void writeDown(Player j, int id, String annotation) {
Set<Sospechoso> set = j.getHojaSospechosos();
for (Sospechoso s : set) {
if (s.getId() == id)
s.setAnnotation(annotation);
}
}
// TODO: implementar esto mediante hash Map
public void buildAbadiaMap() {
tablero.addSquare(new Square(1, "Capilla"));
tablero.addSquare(new Square(2, "Confesionario1"));
tablero.addSquare(new Square(3, "Cripta"));
tablero.addSquare(new Square(4, "Patio"));
tablero.addSquare(new Square(5, "Confesionario2"));
tablero.addSquare(new Square(6, "Claustro1"));
tablero.addSquare(new Square(7, "Claustro2"));
tablero.addSquare(new Square(8, "Claustro3"));
tablero.addSquare(new Square(9, "Hall1"));
tablero.addSquare(new Square(10, "Celda1"));
tablero.addSquare(new Square(11, "Scriptorium"));
tablero.addSquare(new Square(12, "Biblioteca"));
tablero.addSquare(new Square(13, "Hall2"));
tablero.addSquare(new Square(14, "Celda2"));
tablero.addSquare(new Square(15, "Claustro4"));
tablero.addSquare(new Square(16, "Hall3"));
tablero.addSquare(new Square(17, "Celda3"));
tablero.addSquare(new Square(18, "Sala capitular"));
tablero.addSquare(new Square(19, "Hall4"));
tablero.addSquare(new Square(20, "Celda4"));
tablero.addSquare(new Square(21, "Hall5"));
tablero.addSquare(new Square(22, "Celda5"));
tablero.addSquare(new Square(23, "Locutorio"));
tablero.addSquare(new Square(24, "Hall6"));
tablero.addSquare(new Square(25, "Celda6"));
tablero.connectSquare(getSquare(1), getSquare(2));
tablero.connectSquare(getSquare(1), getSquare(3));
tablero.connectSquare(getSquare(1), getSquare(4));
tablero.connectSquare(getSquare(4), getSquare(5));
tablero.connectSquare(getSquare(4), getSquare(6));
tablero.connectSquare(getSquare(6), getSquare(7));
tablero.connectSquare(getSquare(6), getSquare(8));
tablero.connectSquare(getSquare(7), getSquare(15));
tablero.connectSquare(getSquare(7), getSquare(21));
tablero.connectSquare(getSquare(7), getSquare(23));
tablero.connectSquare(getSquare(7), getSquare(24));
tablero.connectSquare(getSquare(8), getSquare(9));
tablero.connectSquare(getSquare(8), getSquare(11));
tablero.connectSquare(getSquare(8), getSquare(13));
tablero.connectSquare(getSquare(8), getSquare(15));
tablero.connectSquare(getSquare(9), getSquare(10));
tablero.connectSquare(getSquare(11), getSquare(12));
tablero.connectSquare(getSquare(13), getSquare(14));
tablero.connectSquare(getSquare(15), getSquare(16));
tablero.connectSquare(getSquare(15), getSquare(18));
tablero.connectSquare(getSquare(15), getSquare(19));
tablero.connectSquare(getSquare(16), getSquare(17));
tablero.connectSquare(getSquare(19), getSquare(20));
tablero.connectSquare(getSquare(21), getSquare(22));
tablero.connectSquare(getSquare(24), getSquare(25));
}
public void giveDeskCardToPlayer(String p, Player j) {
switch(p)
{
case "BIBLIOTECA": notifyViewBiblioCard(j);
break ;
case "SCRIPTORIUM": notifyViewScriptoCard(j);
break;
case "CRIPTA": notifyViewCriptaCard(j);
break;
}
}
private void notifyViewCriptaCard(Player j) {
for (UpdateListener listener : listeners) {
listener.deskCardEventCripta(j);
}
}
private void notifyViewScriptoCard(Player j) {
for (UpdateListener listener : listeners) {
listener.deskCardEventScriptorium(j);
}
}
private void notifyViewBiblioCard(Player j) {
for (UpdateListener listener : listeners) {
listener.deskCardEventLibrary(j);
}
}
public BibliotecaModel getLastLibrary() {
// TODO: barajear las cartas despues de quitar
return biblioteca.getLibraryCards().get(biblioteca.getLibraryCards().size()-1);
}
public ScriptoriumModel getLastScriptoriumCard() {
// TODO: barajear las cartas despues de quitar
return scriptorium.getScriptoriumCards().get(scriptorium.getScriptoriumCards().size()-1);
}
public String getLastCripta() {
// TODO Auto-generated method stub
return cripta.getCriptaCards().get(cripta.getCriptaCards().size()-1);
}
}