#ifndef _TSPRITEARQUERO_CPP_
#define _TSPRITEARQUERO_CPP_

#include "sprites.h"
#include "../escenas/escenarios.h"

REGISTER_CLASS_ID(TSpriteArquero);

int TSpriteArquero::ia_anim[4]={9,10,11,12};

TSpriteArquero::TSpriteArquero(PMAImageBank bank,PMAImageBank bflecha,bool menu):TSpriteGlaurung(bank)
{
	setAnimSequence(ia_anim,4);
	ii_Retardo=4;
	ii_tilesy=3;
	ii_tilesx=2;
	ii_distance_detect=300;
	il_ciclos=0;
	position.width = _ARQUERO_AX;
	position.height = _ARQUERO_AY;
	ib_menu=menu;
	io_flecha = new TSpriteFlecha(bflecha);
	io_flecha->invalidate();
}

TSpriteArquero::~TSpriteArquero()
{
    if (io_flecha!=NULL) delete io_flecha;
}
    
int TSpriteArquero::getHotspotX(void)
{
    if (ib_flip_x)
    {
        return (position.x+40)  / _TileAX;
    }
    return (position.x+10) / _TileAX;
}

int TSpriteArquero::getHotspotY(void)
{
    return (position.y + position.height - 1) / _TileAY;
}
	
/* 
 * Rutina que hace que el arquero ande de derecha a izquierda
 * mientras tenga suelo posible.
 * Cambia de sentido cuando choca con una pared o bien se queda
 * sin suelo sobre el que poder andar.
 */
void TSpriteArquero::walk(void)
{
	int px,py;

    // Calculamos el HOTSPOT del Sprite, para hacer los calculos
	// de detecciones en función de ese punto. 
	// Consideramos ese punto el punto inferior izquierdo.
	//
	py = getHotspotY();
    px = getHotspotX();

	if (ib_flip_x)
	{
        // Determinamos si el arquero puede andar hacia la izquierda
		//
		if ( px>=1 && canWalkLeft(px,py) && isDown(px,py) )
		{
            position.x -= _ARQUERO_ANDANDO;

            // Introducimos un factor de aleatoriedad pequeño que haga
            // cambiar de sentido al personaje.
            //
            if (il_ciclos % 100 == 0) 
            {
                if (miRND.nextInt(500)>250)
                {
                    setFlipX(false);
                    position.x += 40;
                    return;
                }
            }
		}
		else 
		{
            if (px>=1)
			{
				// El arquero comprueba si puede saltar en horizontal
				// hacía la izquierda.
				//
				if (canJumpSmallLeft(px,py,4))
				{
					jumpLeft(4,true);
					return;
				}

				// El arquiero comprueba si puede saltar en arco 
				// hacia la izquierda.
				// 
				if (canJumpBigLeft(px,py,4))
				{
					jumpLeft(4,false);
					return;
				}	
			}

            setFlipX(false);
            position.x += 40;
            return;
	    }
    }
	else
	{
        // Determinamos si el caballero puede andar hacia la derecha
		//
		if ( px<32 && canWalkRight(px,py) && isDown(px,py))
		{
			position.x += _ARQUERO_ANDANDO;
            
            // Introducimos un factor de aleatoriedad pequeño que haga
            // cambiar de sentido al personaje.
            //
            if (il_ciclos % 100 ==0)
            {
                if (miRND.nextInt(500)>250)
                {
                    setFlipX(true);
                    position.x -= 40;
                    return;
                }
            }
		}
		else 
		{
            if (px<32)
			{
				// El arquero comprueba si puede saltar en horizontal
				// hacía la derecha.
				//
				if (canJumpSmallRight(px,py,4))
				{
					jumpRight(4,true);
					return;
				}

				// El arquiero comprueba si puede saltar en arco 
				// hacia la derecha.
				//
				if (canJumpBigRight(px,py,4))
				{
					jumpRight(4,false);
					return;
				}
			}
            setFlipX(true);
            position.x -= 40;
            return;
        }
	}
}

/* 
 * Rutina que hace que el arquero persiga al protagonista.
 * Cambia de sentido cuando choca con una pared o bien se queda
 * sin suelo sobre el que poder andar.
 */
void TSpriteArquero::follow(void)
{
	int px,py,tx,ty;

    // Calculamos el HOTSPOT del Sprite, para hacer los calculos
	// de detecciones en función de ese punto. 
	// Consideramos ese punto el punto inferior izquierdo.
	//
	py = getHotspotY();
    px = getHotspotX();
    
    // Si no hay nada bajo el sprite, hacemos que caiga.
    //
    if ( (!isDown(px,py)) && (py<22) ) 
    {
        position.y += 4;
        return;
    }
    else
    {
        position.y = ((py+1)*_TileAY) - position.height;

        if (io_Target==NULL)
        {
            ii_Estado=0;
            return;
        }

        tx = io_Target->getHotspotX();
        ty = io_Target->getHotspotY(); 
    
        // Caso que estemos asegurados en el suelo, y el personaje principal
        // este fuera de nuestro alcance.
        //
        if (getDistance(*io_Target)>ii_distance_detect)
        {
            ii_Estado--;
            return;
        }
    }

	if (ib_flip_x)
	{
        // *********************************************************************
        // Determinamos si el caballero puede andar hacia la izquierda
		//
		if ( px>1 && canWalkLeft(px,py))
        {
            // Caso que el TARGET se encuentre en el lado contrario
            // hacia donde nos dirigimos.
            // En ese caso seguiremos caminando hasta que topemos con una pared o bien
            // se acabe el suelo..
            //
            if (tx>px)
            {
                if (isDown(px-1,py))
                {
                    position.x -= _ARQUERO_PERSIGUIENDO;
                    return;
                }
                else
                {
                	setFlipX(false);
                    position.x += 40;
                    return;
                }
            }
            else
            {
                // El TARGET se encuentra en la misma dirección en la que vamos.
                // Pero puede encontrarse más alto, más bajo o a la misma altura.

                // Caso que el TARGET este por encima de nosotros...
                //                
                if (ty<py)
                {
                    // Hemos de intentar saltar para subir donde se encuentre...
                    //
                    if (canJumpBigLeft(px,py,4))
				    {
					    jumpLeft(4,false);
					    return;
				    }

                    // Si no podemos saltar, seguiremos andando a menos que se
                    // acabe el suelo.
                    //
                    if (isDown(px-1,py))
                    {
                        position.x -= _ARQUERO_PERSIGUIENDO;
                        return;
                    }
                    else
                    {
                        setFlipX(false);
                        position.x += 40;
                        return;
                    }
                }
                
                // ------------------- AQUI, AQUI

                // Caso que el TARGET se encuentre a la misma algtura que nosotros.
                //
                if (ty==py)
                {
                    // Le disparamos al TARGET
                    //
                    if (il_ciclos % 20==0 && (!io_flecha->isValid()))
                    {
                        io_flecha->init(position.x,position.y+30,ib_flip_x,10);
                        ((TESC_Juego*)miGame->getScene())->addSprite(io_flecha,false);
                    }

                    // Seguimos andando para intentar alcanzarlo, a menos que se 
                    // acabe el suelo.
                    //
                    if (isDown(px-1,py))
                    {
                        position.x -= _ARQUERO_PERSIGUIENDO;
                        return;
                    }
                    else
                    {
                        // Si el suelo se acabe, intentamos realizar un salto corto
                        // para acercarnos al TARGET.
                        //
                        if (canJumpSmallLeft(px-1,py,4))
				        {
					        jumpLeft(4,true);
					        return;
				        }
                        else
                        {
                            // No es posible saltar, así que cambiamos de sentido.
                            ib_flip_x=false;
                            position.x += 40;
                            return;
                        }
                    }
                }

                // Caso que el TARGET se encuentre por debajo de nosotros
                //
                if (ty>py)
                {
                    // Seguimos andando para intentar alcanzarlo, a menos que se 
                    // acabe el suelo.
                    //
                    if (isDown(px-1,py))
                    {
                        position.x -= _ARQUERO_PERSIGUIENDO;
                        return;
                    }
                    else
                    {
                        // Si el suelo se acaba, vemos si podemos dejarnos caer
                        // para acercarnos al TARGET.
                        //
                        if (canFallDown(px,py))
                        {
                            position.x -= _ARQUERO_PERSIGUIENDO;
					        return;
				        }
                        else
                        {
                            // No es posible dejarnos caer, así que cambiamos de sentido.
                            ib_flip_x=false;
                            position.x += 40;
                            return;
                        }
                    }
                }
            }
        }
        else
        {
            // Se ha llegado al limite derecho de la pantalla
            // por lo que cambiamos de sentido.
            //
            ib_flip_x=false;
            position.x += 40;
            return;
        }    
    }
	else
	{
        // *********************************************************************
        // Determinamos si el caballero puede andar hacia la derecha
		//
		if ( px<31 && canWalkRight(px,py))
        {
            // Caso que el TARGET se encuentre en el lado contrario
            // hacia donde nos dirigimos.
            // En ese caso seguiremos caminano hasta que topemos con una pared o bien
            // se acabe el suelo..
            //
            if (tx<px)
            {
                if (isDown(px+1,py))
                {
                    position.x += _ARQUERO_PERSIGUIENDO;
                    return;
                }
                else
                {
                    ib_flip_x=true;
                    position.x -= 40;
                    return;
                }
            }
            else
            {
                // El TARGET se encuentra en la misma dirección en la que vamos.
                // Pero puede encontrarse más alto, más bajo o a la misma altura.

                // Caso que el TARGET este por encima de nosotros...
                //                
                if (ty<py)
                {
                    // Hemos de intentar saltar para subir donde se encuentre...
                    //
                    if (canJumpBigRight(px,py,4))
				    {
					    jumpRight(4,false);
					    return;
				    }

                    // Si no podemos saltar, seguiremos andando a menos que se
                    // acabe el suelo.
                    //
                    if (isDown(px+1,py))
                    {
                        position.x += _ARQUERO_PERSIGUIENDO;
                        return;
                    }
                    else
                    {
                        ib_flip_x=true;
                        position.x -= 40;
                        return;
                    }
                }

                // Caso que el TARGET se encuentre a la misma alguna que nosotros.
                //
                if (ty==py)
                {
                    // Le disparamos al TARGET
                    //
                    if (il_ciclos % 20==0 && (!io_flecha->isValid()))
                    {
                        io_flecha->init(position.x,position.y+30,ib_flip_x,10);
                        ((TESC_Juego*)miGame->getScene())->addSprite(io_flecha,false);
                    }

                    // Seguimos andando para intentar alcanzarlo, a menos que se 
                    // acabe el suelo.
                    //
                    if (isDown(px+1,py))
                    {
                        position.x += _ARQUERO_PERSIGUIENDO;
                        return;
                    }
                    else
                    {
                        // Si el suelo se acabe, intentamos realizar un salto corto
                        // para acercarnos al TARGET.
                        //
                        if (canJumpSmallRight(px+1,py,4))
				        {
					        jumpRight(4,true);
					        return;
				        }
                        else
                        {
                            // No es posible saltar, así que cambiamos de sentido.
                            ib_flip_x=true;
                            position.x -= 40;
                            return;
                        }
                    }
                }

                // Caso que el TARGET se encuentre por debajo de nosotros
                //
                if (ty>py)
                {
                    // Seguimos andando para intentar alcanzarlo, a menos que se 
                    // acabe el suelo.
                    //
                    if (isDown(px+1,py))
                    {
                        position.x += _ARQUERO_PERSIGUIENDO;
                        return;
                    }
                    else
                    {
                        // Si el suelo se acaba, vemos si podemos dejarnos caer
                        // para acercarnos al TARGET.
                        //
                        if (canFallDown(px,py))
                        {
                            position.x += _ARQUERO_PERSIGUIENDO;
					        return;
				        }
                        else
                        {
                            // No es posible dejarnos caer, así que cambiamos de sentido.
                            ib_flip_x=true;
                            position.x -= 40;
                            return;
                        }
                    }
                }
            }
        }
        else
        {
            // Se ha llegado al limite derecho de la pantalla
            // por lo que cambiamos de sentido.
            //
            ib_flip_x=true;
            position.x -= 40;
            return;
        }
    }
}

void TSpriteArquero::animate(void)
{
	switch (ii_EstadoAnim)
	{
	  case 0: // Animación Andando Normal.

		if (ii_RetardoPos<ii_Retardo)
		{
			ii_RetardoPos ++;
		}
		else
		{
			ii_Frame = (ii_Frame<ii_AnimSequenceLength-1)?(ii_Frame+1):0;
			ii_RetardoPos=0;
		}

		break;
	}

	// Si estamos en el menu, no hace nada más.
	//
	if (ib_menu) 
	{
		TSpriteGlaurung::animate();
		return;
	}

	// Si el personaje esta muriendo, no hacemos nada..
    //
    if (ib_muriendo)
    {
    	kill();
        TSpriteGlaurung::animate();
        return;
    }
    
	// Definimos las características del movimiento del personaje.
	// Para ello definiremos un conjunto de estados, que daran lugar
	// a diferentes tipos de comportamiento.
	//
    il_ciclos++;

	switch (ii_Estado)
	{
		case 0:
			if ( (ib_Salto) || (io_Target==NULL) || (getDistance(*io_Target)>ii_distance_detect) )
			{
                if (!ib_Salto) {walk();} else {jump();}
			}
			else
			{
				// Estamos cerca del objetivo, pasamos a perseguirlo.
				ii_Estado++;
			}
            break;

		case 1:
            if (!ib_Salto) {follow();} else {jump();}
            break;            
	}

	TSpriteGlaurung::animate();

	// Si el personaje se sale de los limites de la pantalla
	// lo eliminamos.
	//
	int hy = getHotspotY();
	if (hy>22 || hy<2) invalidate();
}

    
#endif
