#include "Missile.h"

Missile::Missile()
:Shot( MISSILE_DEGAT ), m_xHim( 0 ), m_yHim( 0 ), m_hasTgt( false ), m_decay( 0 ), m_dir( MISSILE_BOOST )
{
    //ctor 1
}

Missile::Missile( Sint16 xMe, Sint16 yMe, bool ally )
:Shot( MISSILE_DEGAT, xMe, yMe, ally ), m_xHim( 0 ), m_yHim( 0 ), m_hasTgt( false ), m_decay( 0 ), m_dir( MISSILE_BOOST )
{
    //ctor 2
}

Missile::Missile( Sint16 xMe, Sint16 yMe, Sint16 xHim, Sint16 yHim, bool ally )
:Shot( MISSILE_DEGAT, xMe, yMe, ally ), m_xHim( xHim ), m_yHim( yHim ), m_hasTgt( true ), m_decay( 0 ), m_dir( MISSILE_BOOST )
{
    //ctor 3
    if ( ally )
        m_decay = abs( yHim - yMe ) / MISSILE_TURN_SPEED;
}

Missile::~Missile()
{
    //dtor
}

void Missile::update()
{
    if ( m_dir == MISSILE_BOOST )
    {
        if ( m_ally )
        {
            m_x -= MISSILE_BOOST_SPEED;
            m_xHim += 1;

            if ( m_hasTgt && m_xHim >= m_x ) turn();
        }
        else
        {
            m_x += MISSILE_BOOST_SPEED;

            if ( m_hasTgt && m_xHim <= m_x ) turn();
        }
    }
    else
    {
        m_y += m_dir * MISSILE_TURN_SPEED;
    }
}

void Missile::draw( SDL_Surface* screen )
{
    if ( !m_exist )
        return;

    switch ( m_dir )
    {
        case MISSILE_BOOST:
            if ( m_ally ) stringRGBA(screen, m_x - 8, m_y - 4, "<-", 255, 120, 0, 255);
            else stringRGBA(screen, m_x - 8, m_y - 4, "->", 255, 120, 0, 255);
            break;
        case MISSILE_DOWN:
            stringRGBA(screen, m_x - 4, m_y - 8, "|", 255, 120, 0, 255);
            stringRGBA(screen, m_x - 4, m_y, "v", 255, 120, 0, 255);
            break;
        case MISSILE_UP:
            stringRGBA(screen, m_x - 4, m_y - 8, "^", 255, 120, 0, 255);
            stringRGBA(screen, m_x - 4, m_y, "|", 255, 120, 0, 255);
            break;
        default:
            stringRGBA(screen, m_x - 4, m_y - 4, "X", 255, 120, 0, 255);
            break;
    }

}

bool Missile::damageSolid( Uint8** solid, const Uint16 dimH, const Uint16 dimW, const SDL_Rect& hitbox )
{
    // Coordonnées impact
    Uint16 yImpct, xImpct;

    if ( m_dir == MISSILE_BOOST )
    {
        // Pénétration axe horizontal
        yImpct = ( m_y - hitbox.y ) / 8;

        if ( m_ally )
            xImpct = dimW - 1;
        else
            xImpct = 0;

        while ( solid[yImpct][xImpct] == 0 )
        {
            if ( m_ally )
                xImpct --;
            else
                xImpct ++;

            if ( xImpct >= dimW )
                return false;
        }
    }
    else
    {
        // Pénétration verticale
        xImpct = ( m_x - hitbox.x ) / 8;

        Sint8 adder( 0 );

        if ( m_dir == MISSILE_UP ) {
            yImpct = dimH - 1;
            adder = MISSILE_UP;
        }
        else {
            yImpct = 0;
            adder = MISSILE_DOWN;
        }

        while ( solid[yImpct][xImpct] == 0 )
        {
            yImpct += adder;

            if ( yImpct >= dimH )
                return false;
        }
    }

    // Déstruction du centre
    damageBloc( solid, dimH, dimW, yImpct, xImpct, 255 );

    // Forts dégats sur l'immédiat
    #define MISSILE_NEAREST_BAM 250
    damageBloc( solid, dimH, dimW, yImpct - 1, xImpct, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct + 1, xImpct, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct, xImpct - 1, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct, xImpct + 1, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct - 1, xImpct - 1, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct + 1, xImpct - 1, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct - 1, xImpct + 1, MISSILE_NEAREST_BAM );
    damageBloc( solid, dimH, dimW, yImpct + 1, xImpct + 1, MISSILE_NEAREST_BAM );

    // Faibles dégats sur l'adjacent
    #define MISSILE_FAR_BAM 200
    damageBloc( solid, dimH, dimW, yImpct - 2, xImpct, MISSILE_FAR_BAM );
    damageBloc( solid, dimH, dimW, yImpct + 2, xImpct, MISSILE_FAR_BAM );
    damageBloc( solid, dimH, dimW, yImpct, xImpct - 2, MISSILE_FAR_BAM );
    damageBloc( solid, dimH, dimW, yImpct, xImpct + 2, MISSILE_FAR_BAM );

    // Déstruction du projectile
    m_exist = false;
    return true;
}

void Missile::turn()
{
    m_x = m_xHim + m_decay ;

    if ( m_yHim > m_y )
        m_dir = MISSILE_DOWN;
    else
        m_dir = MISSILE_UP;
}