package projet.iut.jeu_de_la_vie.model;

import projet.iut.jeu_de_la_vie.model.actualiseur.ActualiseurCellule;
import projet.iut.jeu_de_la_vie.model.actualiseur.ActualiseurTour;
import projet.iut.jeu_de_la_vie.model.actualiseur.ActualiseurTourUnParUn;
import projet.iut.jeu_de_la_vie.model.boucleDeJeu.BoucleDeJeu5FPS;
import projet.iut.jeu_de_la_vie.model.boucleDeJeu.IBoucleDeJeu;
import projet.iut.jeu_de_la_vie.model.boucleDeJeu.observer.ObservableBDJ;
import projet.iut.jeu_de_la_vie.model.boucleDeJeu.observer.ObserverBDJ;
import projet.iut.jeu_de_la_vie.model.cellule.Cellule;
import projet.iut.jeu_de_la_vie.model.cellulesVivantes.CellulesVivantes;
import projet.iut.jeu_de_la_vie.model.plateau.Plateau;


/**
 * Point d'entré du model
 * @author Yohann Breuil
 * @author Allan Point
 */
public class Manager implements ObserverBDJ {
	private ActualiseurTour actualiseurTour;
	private ActualiseurCellule actualiseurCellule;
	private IBoucleDeJeu boucleDeJeu;
	private ChangeurRegle changeurRegle;
	private boolean jeuLance;


	public Manager(){
		boucleDeJeu = new BoucleDeJeu5FPS();
		((ObservableBDJ)boucleDeJeu).attacher(this);
		changeurRegle = new ChangeurRegle();
		Thread thread = new Thread(boucleDeJeu);
		thread.start();
		actualiseurCellule = changeurRegle.changerRegle(new Plateau());
		actualiseurTour = (ActualiseurTour) new ActualiseurTourUnParUn();
		jeuLance = false;
	}

	public void updateOnCellBeforeStart(int x, int y){
		getActualiseurCellule().inverserCellule(x, y);
	}

	public IBoucleDeJeu getBoucleDeJeu() {
		return boucleDeJeu;
	}

	/**
	 * Change l'actualiseur de cellule en fonction des règles
	 */
	private void actualiserActualiseurCellule(){
		actualiseurCellule = changeurRegle.changerRegle(getActualiseurCellule().getArbitre().getPlateau());
	}

	/**
	 * Comportement à adopter quand la boucle de jeu notifie le manager.
	 * (Actualier les cellules et le numéro de génération(tours))
	 */
	@Override
	public void update() {
		if(jeuLance) {
			deleguerChangementCellule();
			actualiseurTour.changerTour();
		}

	}

	public ActualiseurTour getActualiseurTour(){
		return actualiseurTour;
	}

	/**
	 * Actualiser l'état des cellules
	 */
	private void deleguerChangementCellule() {
		CellulesVivantes reference = getActualiseurCellule().getArbitre().getPlateau().getCellulesVivantes().clone();
		for (int y = 0; y<actualiseurCellule.getArbitre().getPlateau().getLigne(); ++y){
			for(int x = 0; x<actualiseurCellule.getArbitre().getPlateau().getColone(); ++x){
				actualiseurCellule.changerCellule(x, y, reference);
			}
		}
	}

	/**
	 * Demende d'inversion de l'état d'une cellule
	 * @param c Cellue à inverser
	 */
	public void inverserEtatCellule(Cellule c){
		getActualiseurCellule().getArbitre().getPlateau().getCell(c.getPosition().getX(), c.getPosition().getY()).inverseAlive();
	}

	public ActualiseurCellule getActualiseurCellule(){
		return actualiseurCellule;
	}

	/**
	 * Authorise le lancement du jeu
	 */
	public void lancerJeu(){
		jeuLance = true;
	}

	/**
	 * Met en pause le jeu
	 */
	public void pauseJeu(){jeuLance = false;}

	/**
	 * Recommencer le jeu
	 */
	public void stoperJeu(){
		actualiseurTour.resetTour();
		//actualiseurCellule.getArbitre().getPlateau().getCellulesVivantes().reset();
		jeuLance = false;
	}

	public ChangeurRegle getChangeurRegle() {
		return changeurRegle;
	}

	public void setNumberOfColumns(int value){
		actualiseurCellule.getArbitre().getPlateau().setColone(value);
	}

	public void setNumberOfLines(int value){
		actualiseurCellule.getArbitre().getPlateau().setLigne(value);
	}

	public int getNumberOfLines(){
		return actualiseurCellule.getArbitre().getPlateau().getLigne();
	}
	public int getNomberOfColumns(){
		return actualiseurCellule.getArbitre().getPlateau().getColone();
	}

	public Cellule getCell(int x, int y){
		return actualiseurCellule.getArbitre().getPlateau().getCell(x, y);
	}

	public void setCellsColor(int color){
		Cellule.setLivingColor(color);
	}

	public Boolean isJeuLance(){
		return jeuLance;
	}
}
