package projet.iut.jeu_de_la_vie.model.plateau;

import projet.iut.jeu_de_la_vie.model.cellulesVivantes.CellulesVivantes;
import projet.iut.jeu_de_la_vie.model.cellule.Cellule;
import projet.iut.jeu_de_la_vie.model.cellule.créateur.CreateurCellule;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Représentation du plateau de jeu
 * @author Yohann Breuil
 * @author Allan Point
 */
public class Plateau implements PrototypePlateau{

	/**
	 * Pour créer corréctement des cellules
	 * @see CreateurCellule
	 */
	private CreateurCellule createurCellule;

	/**
	 * Propriété qui permet de mettre en relation le nombre de colones avec la vue
	 */
	private int colone;
		public int getColone() { return colone;}
		public void setColone(int valeur) { colone = valeur; resetGrille(valeur, getLigne());}

	/**
	 * Propriété qui permet de mettre en relation le nombre de ligne avec la vue
	 */
	private int ligne;
		public int getLigne() { return ligne; }
		public void setLigne(int valeur ) { ligne =valeur; resetGrille(getColone(), valeur);}

	/**
	 * Représentation du plateau dans une liste à 2 dimention
	 */
	private List<List<Cellule>> grille;
		public List<List<Cellule>> getGrille() { return grille; }
		public void setGrille(List<List<Cellule>> cells) {grille = cells;}

	/**
	 * Enssemble des cellules vivante du plateau
	 * @see CellulesVivantes
	 */
	private CellulesVivantes cellulesVivantes;

	/**
	 * Récuperer une cellule sur le plateau
	 * @param x Coordonée x
	 * @param y Coordonée y
	 * @return La cellule positioné en (x; y)
	 * @throws IllegalArgumentException x et y doivent être > 0 et respéctivement inferieur au nombre de colones et de ligne
	 */
	public Cellule getCell(int x, int y) throws IllegalArgumentException{
		if(x < 0 || y < 0) {
			throw new IllegalArgumentException("X ou Y est inférieur à 0");
		}
		if(y >= getGrille().size()){
			throw new IllegalArgumentException("Y est trop grand !!!");
		}
		if(x >= getGrille().get(y).size()){
			throw new IllegalArgumentException("X est trop grand !!!");
		}
		return grille.get(y).get(x);
	}

	/**
	 * Netoyer la grille
	 */
	public void resetGrille(){
			resetGrille(getColone(), getLigne());
	}

	/**
	 * Créer une nouvelle grille
	 * @param colone nombre de colone de la grille
	 * @param ligne nombre de ligne de la grille
	 */
	public void resetGrille(int colone, int ligne){
			setGrille(createurCellule.creerCellules(colone, ligne, cellulesVivantes));
	}

	public Plateau(){
			createurCellule = new CreateurCellule(0, 0);
			cellulesVivantes = new CellulesVivantes();
			setGrille(new LinkedList<>());
	}

	/**
	 *
	 * @param colone Nombre de colones du plateau
	 * @param ligne Nombre de lignes du plateau
	 */
	public Plateau(int colone, int ligne) {
		this(colone, ligne, new CellulesVivantes());
	}

	/**
	 *
	 * @param colone Nombre de colone du plateau
	 * @param ligne Nombre de ligne du plateau
	 * @param observer CellulesVivantes qui veux observer les cellules crées
	 */
	public Plateau(int colone, int ligne, CellulesVivantes observer) {
		createurCellule = new CreateurCellule(colone, ligne);
		setLigne(ligne);
		setColone(colone);
		cellulesVivantes = observer;
		setGrille(createurCellule.creerCellules(cellulesVivantes));
	}

	/**
	 *
	 * @param colone Nombre de colones du plateau
	 * @param ligne Nombre de lignes du plateau
	 * @param cellules Liste en 2 dimentions de cellules
	 */
	public Plateau(int colone, int ligne, List<List<Cellule>> cellules)
	{
		this(colone, ligne);
		setGrille(cellules);
	}

	/**
	 * Clonne un plateau
	 * @return Le même plateau mais avec une référence différente
	 */
	@Override
	public Plateau cloner() {
		return new Plateau(getColone(), getLigne(), getGrille());
	}

	public CellulesVivantes getCellulesVivantes() {
		return cellulesVivantes;
	}

	public void inverserCellule(int x, int y){
		getCell(x, y).inverseAlive();
	}
}
