/*****************************/
/* Inside The Machine - MKS  */
/*****************************/

#include "eEnnemyChuck.h"
#include "../WorldManager.h"

eEnnemyChuck::eEnnemyChuck()
{
	real = true;
	stat = false;
	toDelete = false;
	maxvely = 512;
	velx = vely = 0;  //Vitesse par défaut
	sensH = false;
	//distx = FIX(distx);
	distanceX = 0;
	dontMoveTime = -1;
	life = 15;	
	timeKill = 0;
	killY = 0;
	alpha = 31;
	angryTime = 0;
	isAngry = false;
	hit = false;
	type = 1;
   genre = 0;
	
	//Parametrage des hitboxes
	hitbox.xUp = 8, hitbox.yUp = 1;
	hitbox.xDown = 8, hitbox.yDown = 15;
	hitbox.xLeft = 0, hitbox.yLeft = 8;
	hitbox.xRight = 15, hitbox.yRight = 8;
	
	rect.x1 = 0;
	rect.y1 = 0;
	rect.x2 = 16;
	rect.y2 = 16;
	
	//Paramétrage des états
	isFalling = false;
	isOnTheFloor = false;
	isOnThePente = false;
	isWasOnThePente = false;
	isDontMove = false;
	//ulDebug("Addr:%d\n", this);
}
   	
eEnnemyChuck::~eEnnemyChuck()
{
}

void eEnnemyChuck::Load()
{
   //Chargement du spritesheet
   ulSetTransparentColor(RGB15(31, 0, 31));
	spr.assign(worldMan->resMan->LoadImage("efs:/Ennemy_Chuck.png", UL_IN_VRAM, UL_PF_PAL4));
	sprFx2.assign(worldMan->resMan->LoadImage("efs:/FX_Impact_2.png", UL_IN_VRAM, UL_PF_PAL2));	
	ulDisableTransparentColor();
		
	//Paramètrage des animations
	spr.setFrameWH(16, 16);
	spr.addAnim(0, 0, 3, 7);     //Anim : Course - Left
	spr.addAnim(1, 0, 3, 7);     //Anim : Course - Right
	spr.addAnim(2, 0, 1, 7);     //Anim : Hit - Uni
	spr.addAnim(3, 0, 0, 5);     //Anim : Killed - Left  
	spr.addAnim(3, 1, 0, 5);     //Anim : Killed - Right
	spr.addAnim(0, 4, 3, 3);     //Anim : Course - Angry - Left
	spr.addAnim(1, 4, 3, 3);     //Anim : Course - Angry - Right
	
	sprFx2.scale(32,32);
	sprFx2.setAlpha(true, 20);
}
   
void eEnnemyChuck::Draw(int layer)
{
   //On le perso
   if(actif && layer == 0)
   {
      //On affiche le sprite
   	spr.setXY(x_screen, y_screen);
   	spr.setAlpha(true, alpha);
   	spr.play();
   	if(alpha > 0)
   		spr.draw();
   	
   	//On affiche l'image d'un impact
   	//ulDebug("dmt:%d\n", dontMoveTime);
      if(hit)
      {
	      sprFx2.setXY(x_screen-8, y_screen-8);
	      sprFx2.draw();
		}
		if(dontMoveTime == 10)
			hit = false;
	}	
}
   
void eEnnemyChuck::Update()
{
   //Calcul de la position écran de l'entité
   x_screen = UNFIX(x - FIX(worldMan->curLevel->map->scrollX));
	y_screen = UNFIX(y - FIX(worldMan->curLevel->map->scrollY));
	
	//On vérifie si chuck est actif
   if(x_screen < -16 || x_screen > (256+16) || y_screen < -16 || y_screen > (256))
   	actif = false;
   else
   	actif = true;
   
   if(actif)
   {
      //On vérifie les collisions
      if(life > 0)
	   	CheckCollisions();
	   
	   //On vérifie si Chuck est énervé...
	   angryTime++;
	   if(angryTime > 180)
	   	angryTime = 0;
	   
	   //On calcule la distance parcourue en X au sol
   	if(oldx < x && isOnTheFloor)
   		distanceX += x-oldx;
   	/*if(oldx == x)
   		distanceX = 0;*/
   	if(oldx > x && isOnTheFloor)
   		distanceX -= oldx-x;
		
      //On change le sens de déplacement
      if(distanceX > distx)
      	sensH = false;
      if(distanceX < -distx)
      	sensH = true;
      
      //ulDebug("life:%d\n", life);
      if(life > 0)
      {
	      //On fait faire une ronde au personnage
	      if(sensH)
	      {
	      	if(isOnTheFloor && dontMoveTime == -1)
	      	{
	      	   if(angryTime > 120)
	      	   {
						velx = vitesse*2;
						spr.animLoop(5);
						isAngry = true;
					}
					else
					{
						velx = vitesse;
						spr.animLoop(0);
						isAngry = false;
					}					
				}			
				else
					velx = 0;
	      }
			else
			{
			 	if(isOnTheFloor && dontMoveTime == -1)
			 	{
			 	   if(angryTime > 120)
	      	   {
						velx = -vitesse*2;
						spr.animLoop(6);
						isAngry = true;
					}
					else
					{
						velx = -vitesse;
						spr.animLoop(1);
						isAngry = false; 
					}						
				}			
				else
					velx = 0;
			}
			if(dontMoveTime > -1)
			{
			   //On arrête le mouvement du perso
			   spr.animLoop(2);
				dontMoveTime--;
			}	
		}
		else
		{
		   if(dontMoveTime > -1)
			{
			   //On arrête le mouvement du perso
				dontMoveTime--;
			}
		   //Update du dead time
		   timeKill++;
		   	
		   //Lire l'animation de mort
		   if(sensH)
	      {
	         spr.animLoop(3);
	      }
			else
			{
			   spr.animLoop(4);
			}
			
			if(timeKill > 60)
				alpha--;
			if(alpha < 0)
				alpha = 0;
				
			//Destruction de l'entité
			if(timeKill > 90)
				toDelete = true;		   
		}								   
	}	
}

void eEnnemyChuck::CheckCollisions()
{
	//1ère Etape : Prédiction de collisions avec les bords de la map
	if(x < 0)
	{
		x = 0;
		sensH = -sensH;
	}		
	if(x > FIX((worldMan->curLevel->lx*16) - 32))
	{
		x = FIX((worldMan->curLevel->lx*16) - 32);
		sensH = -sensH;
	}		
	if(y < 0)
		y = 0;
	if(y > FIX((worldMan->curLevel->ly*16)) )
		y = FIX(worldMan->curLevel->ly*16);
	
	//SUB : On vérifie si il faut aprtir dans l'autre sens a cause du vide
	/*if(isOnTheFloor && uGetMapPixel(worldMar->curLevel->map_coll, UNFIX(x), UNFIX(y), NULL, NULL, NULL) == 1)
		ulDebug("vide\n");*/
	
	//2ème Etape : Prediction de collisions avec les pentes
	bool isPenteFound = false;
	isWasOnThePente = isOnThePente;
	isOnThePente = false;
	if(vely > 0)
	{
		//On déclare des variables pour le point de test des collisions
		int testx = UNFIX(x + velx) + hitbox.xDown;
		int testy = UNFIX(y + vely) + hitbox.yDown-1;
		
		//On récupère le tile qui comprends le point de test
		u16 tile = 0;
		
		//On déclare une structure temporaire
		PenteInfo val;
		
		//On teste si le prochain pixel est bleu (le pixel juste en face)
		if(uGetMapPixel(worldMan->curLevel->map_coll, testx, testy, &tile, NULL, NULL) == 3)
		{
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;				
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}		
		}
		else if(uGetMapPixel(worldMan->curLevel->map_coll, testx, testy-1, &tile, NULL, NULL) == 3)
		{
		   //On fait un 2ème test sur le pixel juste au dessus
		   testy = testy-1;
			//On déclare une structure temporaire
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}	
		}
		else if(uGetMapPixel(worldMan->curLevel->map_coll, testx + 1, testy, &tile, NULL, NULL) == 3)
		{
		   //On fait un 2ème test sur le pixel juste à côté
		   testy = testy;
		   testx = testx + 1;
			//On déclare une structure temporaire
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}	
		}
		else if(uGetMapPixel(worldMan->curLevel->map_coll, testx - 1, testy, &tile, NULL, NULL) == 3)
		{
		   //On fait un 2ème test sur le pixel juste à côté
		   testy = testy;
		   testx = testx - 1;
			//On déclare une structure temporaire
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}	
		}
	}
	   
	//3ème Etape : Prédiction de collisions avec les côtés
	if(isPenteFound == false)
	{
		if(velx > 0)
		{
			if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x + velx) + hitbox.xRight, UNFIX(y) + hitbox.yRight, NULL, NULL, NULL) == 2)
			{
				x = oldx;
				sensH = !sensH;
			}			
			else
				x += velx; 
		}   
		if(velx < 0)
		{
			if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x + velx) + hitbox.xLeft, UNFIX(y) + hitbox.yLeft, NULL, NULL, NULL) == 2)
			{
				x = oldx;
				sensH = !sensH;
			}
			else
				x += velx; 
		}
		
		//4ème Etape : Prédiction de collisions avec le sol et le plafond
		if(vely < 0)
		{
		   /*if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x) + hitbox.xUp, UNFIX(y + vely) + hitbox.yUp, NULL, NULL, NULL) == 2)
		   {
				//y = oldy;
				vely = 0;
				isFalling = true;
				isOnTheFloor = false;
			}		
			else
			{
			   isFalling = true;
			   isOnTheFloor = false;
				y += vely;
				vely += worldMan->curLevel->vgy;
				if(vely >=maxvely)
					vely = maxvely;
			}*/		
		}
		else
		{
		   if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x) + hitbox.xDown, UNFIX(y + vely) + hitbox.yDown, NULL, NULL, NULL) == 2)
		   {
				//y = oldy;
				vely = 256;
				isFalling = false;
				isOnTheFloor = true;
				//On teste le pixel juste au dessus
				 
			}	
			else
			{
			   if(isWasOnThePente)
			   	isFalling = false;
			   else
			   	isFalling = true;
			   isOnTheFloor = false;
				y += vely;
				vely += worldMan->curLevel->vgy;
				if(vely >= maxvely)
					vely = maxvely;
			}
		}
	} 
}
   
void eEnnemyChuck::CheckInteractions()
{
   //On vérifie d'abord si un coup du perso touche au sol
   if(worldMan->hero->isGroundBattle && life > 0)
   {
   	if(worldMan->hero->sensH)
		{
			//Collision combo coup droit 
			if(RectCollision(UNFIX(x), UNFIX(y), &rect, UNFIX(worldMan->hero->x), UNFIX(worldMan->hero->y), &worldMan->hero->rectBattleRight) )
			{
			   if(dontMoveTime == -1)
			   {
			   	life -= 5;
			   	hit = true;
			   	dontMoveTime = 15;
				}   
			}   
		}
		else
		{
		   //Collision combo coup gauche
			if(RectCollision(UNFIX(x), UNFIX(y), &rect, UNFIX(worldMan->hero->x), UNFIX(worldMan->hero->y), &worldMan->hero->rectBattleLeft) )
			{
			   if(dontMoveTime == -1)
			   {
			   	life -= 5;
			   	hit = true;
			   	dontMoveTime = 15;
				} 
			}
		}						 
   }
   
   //Collision avec les fireballs du héros
	for(int k = 0; k < BULLETMAX; k++)
	{
	   if(worldMan->hero->bullets[k].actif == true)
	   {
	   	if(RectCollision(worldMan->hero->bullets[k].x, worldMan->hero->bullets[k].y, &worldMan->hero->bullets[k].rect, UNFIX(x), UNFIX(y), &rect) )
	   	{
		   	if(dontMoveTime == -1)
				{
					dontMoveTime = 20;
					//On fait perdre de la vie aussi
					life -= 1;
					hit = true;
					worldMan->hero->bullets[k].actif = false;
				}
	      }						  
	   }   
	} 
   
	//Collisions avec le personnage (on enlève de la vie)  if(worldMan->hero->dontMoveTime == -1)		  
	if(life > 0 && isAngry && RectCollision(UNFIX(x), UNFIX(y), &rect, UNFIX(worldMan->hero->x), UNFIX(worldMan->hero->y), &worldMan->hero->rect) )
	{
	   if(worldMan->hero->dontHitTime == -1)
	   {
			worldMan->hero->dontHitTime = 30;
			worldMan->hero->dontMoveTime = 3;
			worldMan->hero->life -= 5;
		}		
	}   
}   

void eEnnemyChuck::Destroy()
{
   //On libère le sprite
   /*spr.free();
   worldMan->DeleteMe(this);*/
}
