#include <list>
#include <iostream>
#include <SDL/SDL.h>
#include "constantes.hpp"
#include "cSerpent.hpp"
#include "cPoint.hpp"





cSerpent::cSerpent() {

	(this->serpent).push_back(cPoint(XDEP, YDEP));
	(this->serpent).push_back(cPoint(XDEP-1, YDEP));
	(this->serpent).push_back(cPoint(XDEP-2, YDEP));

	this->pPoint = SDL_CreateRGBSurface(SDL_SWSURFACE, BLOC, BLOC, 32, 0, 0, 0, 0);

	this->direction = EST;

	this->agrandissement = 0;

	(this->pomme) = cPomme();
	(this->pomme).aleatoire();
}



void cSerpent::set_direction(int direction) {

		bool autorise = true;

		switch (this->direction) {

			case NORD :
				if (direction == SUD) { autorise = false; }; break;

			case EST :
				if (direction == OUEST) { autorise = false; }; break;

			case SUD :
				if (direction == NORD) { autorise = false; }; break;

			case OUEST :
				if (direction == EST) { autorise = false; }; break;

		}


		if (autorise == true) {
			this->direction = direction;
		}

}



void cSerpent::set_agrandissement(int agrandissement) {
	this->agrandissement = agrandissement;
}

int cSerpent::get_agrandissement() {
	return this->agrandissement;
}





void cSerpent::affiche(SDL_Surface* pScreen) {

	for (std::list<cPoint>::iterator i = (serpent).begin(); i != (serpent).end(); i++) {
		(*i).affiche(pPoint, pScreen);
	}

	(this->pomme).affiche(pPoint, pScreen);

	SDL_Flip(pScreen);

}



bool cSerpent::deplace() {

	int new_x = (this->serpent).front().get_x();
	int new_y = (this->serpent).front().get_y();


	switch (this->direction) {
		case NORD 	:	new_y--; break;
		case EST	:	new_x++; break;
		case SUD	: 	new_y++; break;
		case OUEST	:	new_x--; break;
		default : break;
	}


	if (new_y < 0 || new_y >= YMAX || new_x < 0 || new_x >= XMAX || this->se_tue() == true) {

		return false;	// retourne -1 si sort des limites de l'écran

	} else {

		/*--- si le serpent est sur la pomme, alors on génère une nouvelle
		 pomme et on indique qu'il faut agrandir le serpent ---*/
		if (this->mangePomme() == true) {
			
			(this->pomme).aleatoire();
			this->agrandissement = AGRANDISSEMENT;

		} 



		/*----- si l'agrandissement supérieur à 0, on n'efface pas l'élément de
		queue du snake pour simuler l'agrandissement du serpent -----*/
		if (this->agrandissement == 0) {

			(this->serpent).pop_back();		// supprime l'élément de tête

		} else {

			this->agrandissement--;			// diminue le nombre d'agrandissements

		}



		(this->serpent).push_front(cPoint(new_x, new_y));	// ajoute le nouvel élement en tete

		return true;
	}


}



bool cSerpent::mangePomme() {

	bool trouve = false;	// condition de sortie anticipée du while
	std::list<cPoint>::iterator i = (this->serpent).begin();	// iterateur


	/*--- parcourt l'ensemble du serpent tant que ne se trouve pas sur la pomme
	et que la fin du serpent n'est pas atteinte ---*/

	while (trouve == false && i != (this->serpent).end()) {

		if ( (*i).get_x() == (this->pomme).get_x() && (*i).get_y() == (this->pomme).get_y() ) {
			trouve = true;
		}

		i++;
	}


	return trouve;
}


bool cSerpent::se_tue() {

	bool trouve = false;	// condition de sortie anticipée du while
	std::list<cPoint>::iterator i = (this->serpent).begin();	// iterateur
	i++;	// on se déplace au second point du serpent

	/*--- vérifie si la tête du serpent ne se trouve pas sur un point ou se
	trouve déjà son corps ---*/

	while (trouve == false && i != (this->serpent).end()) {

		if ( (*i).get_x() == (this->serpent).front().get_x() && (*i).get_y() == (this->serpent).front().get_y() ) {
			trouve = true;
		}

		i++;
	}


	return trouve;
}


cSerpent::~cSerpent() {

}
