#include <Xtreme/XRenderer.h>

#include ".\BirdiesRevenge.h"
#include ".\birdie.h"
#include ".\Level.h"
#include ".\Note.h"



Birdie::Birdie() :
  m_FireDelay( 0.0f ),
  m_FireMoveDelay( 0.0f ),
  m_RecoilSpeed( 0 ),
  m_RecoilSpeedDelay( 0 ),
  m_MovementSlowDownDelay( 0 ),
  m_FastNotes( false ),
  m_FartherNotes( false ),
  m_SmallerFireDelay( false )
{
  m_Type = Birdie2::UT_BIRDIE;

  m_MovementBounds.set( 0, 0, 40, 40 );
  m_CollisionBounds.set( 5, 5, 30, 30 );

  m_WalkSpeed = 0;
  m_Dying = false;

  m_Gun = false;
  m_Uzi = false;

  SetAnimation( "Player.Stand" );
}



void Birdie::UpdateFixed( Level& Level )
{
  if ( m_Dying )
  {
    return;
  }

  if ( theApp.InputClass()->VKeyPressed( theApp.BoundKey( Birdie2::ControlKey::LEFT ) ) )
  {
    if ( m_FireMoveDelay == 0.0f )
    {
      m_MovementSlowDownDelay = 0;
      m_Speed.x = math::maxValue( m_Speed.x - 3, -4 );

      if ( m_OnGround )
      {
        if ( m_Uzi )
        {
          SetAnimation( "Player.WalkUzi" );
        }
        else if ( m_Gun )
        {
          SetAnimation( "Player.WalkGun" );
        }
        else
        {
          SetAnimation( "Player.Walk" );
        }
      }
    }
  }
  else if ( theApp.InputClass()->VKeyPressed( theApp.BoundKey( Birdie2::ControlKey::RIGHT ) ) )
  {
    if ( m_FireMoveDelay == 0.0f )
    {
      m_MovementSlowDownDelay = 0;

      m_Speed.x = math::minValue( m_Speed.x + 3, 4 );
      if ( m_OnGround )
      {
        if ( m_Uzi )
        {
          SetAnimation( "Player.WalkUzi" );
        }
        else if ( m_Gun )
        {
          SetAnimation( "Player.WalkGun" );
        }
        else
        {
          SetAnimation( "Player.Walk" );
        }
      }
    }
  }
  else
  {
    ++m_MovementSlowDownDelay;
    if ( m_MovementSlowDownDelay >= 2 )
    {
      m_MovementSlowDownDelay = 0;
      if ( m_Speed.x < 0 )
      {
        ++m_Speed.x;
      }
      if ( m_Speed.x > 0 )
      {
        --m_Speed.x;
      }
    }
    if ( m_OnGround )
    {
      if ( m_FireMoveDelay > 0.25f )
      {
        if ( m_Uzi )
        {
          SetAnimation( "Player.FireUzi" );
        }
        else if ( m_Gun )
        {
          SetAnimation( "Player.FireGun" );
        }
        else
        {
          SetAnimation( "Player.Fire" );
        }
      }
      else
      {
        if ( m_Uzi )
        {
          SetAnimation( "Player.StandUzi" );
        }
        else if ( m_Gun )
        {
          SetAnimation( "Player.StandGun" );
        }
        else
        {
          SetAnimation( "Player.Stand" );
        }
      }
    }
  }

  Unit::UpdateFixed( Level );
  if ( m_RecoilSpeed != 0 )
  {
    Move( Level, GR::tPoint( m_RecoilSpeed, 0 ) );
    ++m_RecoilSpeedDelay;
    if ( m_RecoilSpeedDelay >= 2 )
    {
      m_RecoilSpeedDelay = 0;
      if ( m_RecoilSpeed < 0 )
      {
        ++m_RecoilSpeed;
      }
      if ( m_RecoilSpeed > 0 )
      {
        --m_RecoilSpeed;
      }
      m_NoAutoAdjustFacing = ( m_RecoilSpeed != 0 );
    }

  }
}



Note* Birdie::NewNote( Level& Level )
{
  Note*    pNote = (Note*)Unit::FromType( Birdie2::UT_NOTE );
  if ( pNote )
  {
    pNote->m_Position = m_Position;
    if ( m_FaceLeft )
    {
      pNote->MoveUnblocked( Level, -20, 0 );
      pNote->Move( Level, GR::tPoint( -20, 0 ) );
      pNote->m_FaceLeft = true;
    }
    else
    {
      pNote->MoveUnblocked( Level, 20, 0 );
      pNote->Move( Level, GR::tPoint( 20, 0 ) );
      pNote->m_FaceLeft = false;
    }
    if ( m_FartherNotes )
    {
      pNote->m_DistanceToFly = 300;
    }
    if ( m_FastNotes )
    {
      pNote->m_WalkSpeed = 15;
    }
    
    Level.m_Units.push_back( pNote );
  }
  return pNote;
}



void Birdie::Update( Level& Level, const GR::f32 fElapsedTime )
{
  if ( !m_Dying )
  {
    if ( m_FireDelay > 0.0f )
    {
      m_FireDelay -= fElapsedTime;
      if ( m_FireDelay <= 0.0f )
      {
        m_FireDelay = 0.0f;
      }
    }
    if ( m_FireMoveDelay > 0.0f )
    {
      m_FireMoveDelay -= fElapsedTime;
      if ( m_FireMoveDelay <= 0.0f )
      {
        m_FireMoveDelay = 0.0f;
      }
    }
    if ( theApp.InputClass()->VKeyPressed( theApp.BoundKey( Birdie2::ControlKey::JUMP ) ) )
    {
      if ( Jump( 16 ) )
      {
        theApp.SoundClass()->Play( theApp.Sound( "Player.Jump" ) );
      }
      if ( m_Jumping )
      {
        if ( m_FireMoveDelay >= 0.25f )
        {
          if ( m_Uzi )
          {
            SetAnimation( "Player.Jump.FireUzi" );
          }
          else if ( m_Gun )
          {
            SetAnimation( "Player.Jump.FireGun" );
          }
          else
          {
            SetAnimation( "Player.Jump.Fire" );
          }
        }
        else
        {
          if ( m_Uzi )
          {
            SetAnimation( "Player.JumpUzi" );
          }
          else if ( m_Gun )
          {
            SetAnimation( "Player.JumpGun" );
          }
          else
          {
            SetAnimation( "Player.Jump" );
          }
        }
      }
    }
    else
    {
      if ( m_Jumping )
      {
        m_Jumping = false;
      }
    }
    if ( theApp.InputClass()->VKeyPressed( theApp.BoundKey( Birdie2::ControlKey::ACTION ) ) )
    {
      if ( m_FireDelay == 0.0f )
      {
        if ( m_Gun )
        {
          m_FireMoveDelay = 0.4f;
          m_FireDelay = 0.8f;
        }
        else if ( m_Uzi )
        {
          m_FireMoveDelay = 0.1f;
          m_FireDelay = 0.05f;
        }
        else
        {
          m_FireDelay = 0.8f;
        }
        if ( m_SmallerFireDelay )
        {
          m_FireDelay *= 0.5f;
        }

        theApp.SoundClass()->Play( theApp.Sound( "Player.Fire" ) );

        if ( m_Gun )
        {
          // 5 notes!
          for ( int i = 0; i < 5; ++i )
          {
            Note*   pNote = NewNote( Level );
            pNote->m_Speed.y = -2 + 1 * i;
          }
          // recoil
          if ( m_FaceLeft )
          {
            m_RecoilSpeed = 5;
          }
          else
          {
            m_RecoilSpeed = -5;
          }
          m_RecoilSpeedDelay = 0;
          m_NoAutoAdjustFacing = true;
        }
        else
        {
          Note*   pNote = NewNote( Level );
          if ( m_Uzi )
          {
            // recoil
            if ( m_FaceLeft )
            {
              m_RecoilSpeed = 2;
            }
            else
            {
              m_RecoilSpeed = -2;
            }
            m_RecoilSpeedDelay = 0;
            m_NoAutoAdjustFacing = true;
          }
        }
        if ( m_OnGround )
        {
          if ( m_Uzi )
          {
            SetAnimation( "Player.FireUzi" );
          }
          else if ( m_Gun )
          {
            SetAnimation( "Player.FireGun" );
          }
          else
          {
            SetAnimation( "Player.Fire" );
          }
        }
        else
        {
          if ( m_Uzi )
          {
            SetAnimation( "Player.Jump.FireUzi" );
          }
          else if ( m_Gun )
          {
            SetAnimation( "Player.Jump.FireGun" );
          }
          else
          {
            SetAnimation( "Player.Jump.Fire" );
          }
        }
      }
    }

    if ( ( !m_Jumping )
    &&   ( !m_OnGround ) )
    {
      if ( m_FireDelay < 0.5f )
      {
        if ( m_Uzi )
        {
          SetAnimation( "Player.FallUzi" );
        }
        else if ( m_Gun )
        {
          SetAnimation( "Player.FallGun" );
        }
        else
        {
          SetAnimation( "Player.Fall" );
        }
      }
    }
  }
  Unit::Update( Level, fElapsedTime );
}



void Birdie::ProcessEvent( Level& Level, const eUnitEvent& Event )
{

  Unit::ProcessEvent( Level, Event );

  switch ( Event )
  {
    case ET_FALL_START:
      if ( m_Uzi )
      {
        SetAnimation( "Player.FallUzi" );
      }
      else if ( m_Gun )
      {
        SetAnimation( "Player.FallGun" );
      }
      else
      {
        SetAnimation( "Player.Fall" );
      }
      break;
    case ET_FALL_END:
      if ( m_Uzi )
      {
        SetAnimation( "Player.StandUzi" );
      }
      else if ( m_Gun )
      {
        SetAnimation( "Player.StandGun" );
      }
      else
      {
        SetAnimation( "Player.Stand" );
      }
      break;
  }

}