#include "Player.h"
#include "LD.h"
#include "Level.h"
#include "PlayerShot.h"
#include "Particle.h"
#include "Fire.h"



Player::Player() :
  Angle( 0.0f ),
  MovedDistance( 0.0f ),
  DroppingRope( false ),
  pLastTouchedPlanet( NULL ),
  CurrentRopeIndex( 0 ),
  CurrentPieceIndex( 0 ),
  RopeColor( 0xffff00ff ),
  pStartPlanet( NULL ),
  FireDelay( 0 ),
  ShipLoopActive( false )
{
  Type = LD::GO_PLAYER;
}



void Player::Display( IDirect3DDevice8* pDevice )
{
  theApp.RenderTextureSectionRotated2d( Position.x,
                                        Position.y,
                                        theApp.m_TexSec[LD::TEX_PLAYER_SHIP],
                                        -Angle, 
                                        1.0f,
                                        Color );
  /*
  LD::PointF      p1( 0, -23 );
  p1.RotateZ( Angle );
  LD::PointF      p2( 23, 23 );
  p2.RotateZ( Angle );
  LD::PointF      p3( -23, 23 );
  p3.RotateZ( Angle );

  theApp.RenderLine2d( Position + LD::Point( (int)p1.x, (int)p1.y ), Position + LD::Point( (int)p2.x, (int)p2.y ), 0xff00ff00 );
  theApp.RenderLine2d( Position + LD::Point( (int)p2.x, (int)p2.y ), Position + LD::Point( (int)p3.x, (int)p3.y ), 0xff00ff00 );
  theApp.RenderLine2d( Position + LD::Point( (int)p3.x, (int)p3.y ), Position + LD::Point( (int)p1.x, (int)p1.y ), 0xff00ff00 );
  */
}



void Player::UpdateFixedTimeStep( Level& theLevel )
{
  Speed *= 0.95f;
  Speed += Acceleration;

  if ( ( Acceleration.x != 0.0f )
  ||   ( Acceleration.y != 0.0f ) )
  {
    //FireDelay = ( FireDelay + 1 ) % 4;

    if ( FireDelay == 0 )
    {
      Fire*   pFire = new Fire();
      pFire->Speed.set( 0.0f, 40.0f );
      pFire->Speed.RotateZ( -Angle + ( rand() % 61 ) - 30 );
      pFire->LifeTime = ( rand() % 100 ) * 0.01f + 0.75f;
      theLevel.AddDecoUnit( pFire, TailPos( -6, 0 ) - LD::Point( 3, 3 ) );

      pFire = new Fire();
      pFire->Speed.set( 0.0f, 40.0f );
      pFire->Speed.RotateZ( -Angle + ( rand() % 61 ) - 30 );
      pFire->LifeTime = ( rand() % 100 ) * 0.01f + 0.75f;
      theLevel.AddDecoUnit( pFire, TailPos( 6, 0 ) - LD::Point( 3, 3 ) );
    }
  }
  if ( ( theApp.m_KeyPressed[VK_SPACE] )
  ||   ( theApp.m_KeyPressed['X'] ) )
  {
    theApp.m_KeyReleased[VK_SPACE] = false;
    theApp.m_KeyReleased['X'] = false;

    theApp.PlaySoundA( LD::SOUND_SHOT );

    PlayerShot*   pShot = new PlayerShot();

    pShot->Speed.set( 0.0f, -240.0f );
    pShot->Speed.RotateZ( -( -Angle + ( rand() % 21 ) - 10 ) );
    pShot->LifeTime = ( rand() % 100 ) * 0.01f + 0.75f;
    theLevel.AddUnit( pShot, GunPos().x, GunPos().y );
  }
}



LD::Point Player::TailPos( int DX, int DY )
{
  LD::Point     curPos = Position;

  LD::Point     tailOffset( DX + 0, DY + 24 );

  tailOffset.RotateZ( Angle );

  return curPos + tailOffset;
}



LD::Point Player::GunPos()
{
  LD::Point     curPos = Position;

  LD::Point     tailOffset( 0, -24 );

  tailOffset.RotateZ( Angle );

  return curPos + tailOffset;
}



void Player::Update( Level& theLevel, float ElapsedTime )
{
  int     x1 = ( Position.x - 10 ) / 32;
  int     y1 = ( Position.y - 10 ) / 32;
  int     x2 = ( Position.x + 10 + 31 ) / 32;
  int     y2 = ( Position.y + 10 +31 ) / 32;

  for ( int x = x1; x <= x2; ++x )
  {
    for ( int y = y1; y <= y2; ++y )
    {
      if ( theLevel.Grid[x][y] )
      {
        // player killed
        theApp.PlaySoundA( LD::SOUND_PLAYER_DIED );
        RemoveMe = true;

        for ( int i = 0; i < 100; ++i )
        {
          Particle*  pPart = new Particle();
          pPart->Position = Position;
          pPart->Speed.set( 50.0f + rand() % 100, 0.0f );
          pPart->Speed.RotateZ( (float)( rand() % 360 ) );
          pPart->LifeTime = ( rand() % 100 ) * 0.01f + 0.75f;

          theLevel.AddDecoUnit( pPart );
        }
        return;
      }
    }
  }

  if ( theApp.m_KeyPressed[VK_LEFT] )
  {
    Angle -= 120.0f * ElapsedTime;
  }
  if ( theApp.m_KeyPressed[VK_RIGHT] )
  {
    Angle += 120.0f * ElapsedTime;
  }
  Acceleration.clear();
  if ( theApp.m_KeyPressed[VK_UP] )
  {
    Acceleration.set( 0.0f, -20.0f );
    Acceleration.RotateZ( Angle );

    if ( !ShipLoopActive )
    {
      ShipLoopActive = true;
      //theApp.LoopSound( LD::SOUND_SHIP_LOOP );
    }
  }
  else if ( theApp.m_KeyPressed[VK_DOWN] )
  {
    Acceleration.set( 0.0f, 20.0f );
    Acceleration.RotateZ( Angle );

    if ( !ShipLoopActive )
    {
      ShipLoopActive = true;
      //theApp.LoopSound( LD::SOUND_SHIP_LOOP );
    }
  }
  else
  {
    if ( ShipLoopActive )
    {
      ShipLoopActive = false;
      //theApp.StopSound( LD::SOUND_SHIP_LOOP );
    }
  }

  FractPos += Speed * ElapsedTime;
  AdjustFractPos( true );
}
