#include <d3d8.h>

#include "GSGame.h"
#include "GSMenu.h"
#include "GSDone.h"
#include "LD.h"
#include "Player.h"
#include "Cloud.h"
#include "Ufo.h"
#include "Emerald.h"



GSGame::GSGame()
{
  m_LastScore = 0;
  RestartGame();
}



GSGame::~GSGame()
{
}



void GSGame::RestartGame()
{
  m_TickDelay = 0.0f;
  m_NumTicks = 0;
  m_GrowDelay = 12;

  m_Level.ClearUnits();
  m_Level.Score = 0;
  m_Level.NumEmeralds = 0;

  Player*   pPlayer = new Player();
  pPlayer->Position.set( 1024 / 2, 768 / 2 );
  pPlayer->LastMovementPos = pPlayer->Position;

  m_Level.AddUnit( pPlayer, pPlayer->Position.x, pPlayer->Position.y );
  m_Level.pPlayer = pPlayer;

  for ( int i = 0; i <= 768 / 32; ++i )
  {
    Cloud*  pCloud = new Cloud();
    pCloud->ZoomFactor = 0.9f + ( rand() % 100 ) * 0.012f;
    pCloud->RotationDelta = -90.0f + ( rand() % 181 );
    pCloud->Position.set( 1024, i * 32 );
    m_Level.AddDecoUnit( pCloud );
    m_Level.CloudUnits[32][i] = pCloud;

    pCloud = new Cloud();
    pCloud->ZoomFactor = 0.9f + ( rand() % 100 ) * 0.012f;
    pCloud->RotationDelta = -90.0f + ( rand() % 181 );
    pCloud->Position.set( 0, i * 32 );
    m_Level.AddDecoUnit( pCloud );
    m_Level.CloudUnits[0][i] = pCloud;
  }
  for ( int i = 1; i < 1024 / 32; ++i )
  {
    Cloud*  pCloud = new Cloud();
    pCloud->ZoomFactor = 0.9f + ( rand() % 100 ) * 0.012f;
    pCloud->RotationDelta = -90.0f + ( rand() % 181 );
    pCloud->Position.set( i * 32, 0 );
    m_Level.AddDecoUnit( pCloud );
    m_Level.CloudUnits[i][0] = pCloud;

    pCloud = new Cloud();
    pCloud->ZoomFactor = 0.9f + ( rand() % 100 ) * 0.012f;
    pCloud->RotationDelta = -90.0f + ( rand() % 181 );
    pCloud->Position.set( i * 32, 768 );
    m_Level.AddDecoUnit( pCloud );
    m_Level.CloudUnits[i][24] = pCloud;
  }
  m_Level.GrowTile();
}



void GSGame::Display( IDirect3DDevice8* pDevice )
{
  pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

  pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

  pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );

  m_Level.Display( pDevice );

  if ( m_Level.pPlayer == NULL )
  {
    theApp.PrintNiceCentered( 512, 768 / 2, "GAME OVER" );

    theApp.Print( 5, 768 - 20, "Press ESC to end game" );
    theApp.Print( 1024 - 180, 768 - 20, "Press SPACE or X to try again" );
  }

  char    temp[200];
  sprintf( temp, "BEST: %08d", m_LastScore );
  theApp.PrintNice( 10, 10, temp );

  sprintf( temp, "SCORE: %08d", m_Level.Score );
  theApp.PrintNiceCentered( 512, 10, temp );

  sprintf( temp, "DATA CRYSTALS: %d/10", m_Level.NumEmeralds );
  theApp.PrintNiceRightAligned( 1024 - 10, 10, temp );
}



void GSGame::UpdateFixed()
{
  ++m_NumTicks;
  if ( ( m_NumTicks % m_GrowDelay ) == 0 )
  {
    m_Level.GrowTile();
  }

  if ( m_Level.pPlayer != NULL )
  {
    if ( ( m_NumTicks % 200 ) == 0 )
    {
      Ufo*    pUfo = new Ufo();

      pUfo->m_TargetPos.set( ( rand() % 32 ) * 32 + 16.0f, ( rand() % 24 ) * 32 + 16.0f );

      // spawn outside the border
      switch ( rand() % 4 )
      {
        case 0:
          m_Level.AddUnit( pUfo, ( rand() % 32 ) * 32 + 16, -48 );
          break;
        case 1:
          m_Level.AddUnit( pUfo, -48, ( rand() % 24 ) * 32 + 16 );
          break;
        case 2:
          m_Level.AddUnit( pUfo, ( rand() % 32 ) * 32 + 16, 768 + 48 );
          break;
        case 3:
          m_Level.AddUnit( pUfo, 1024 + 48, ( rand() % 24 ) * 32 + 16 );
          break;
      }
      theApp.PlaySoundA( LD::SOUND_SPAWN_UFO );
    }

    if ( ( m_NumTicks % 1024 ) == 0 )
    {
      Emerald*   pEmerald = new Emerald();

      for ( int i = 0; i < 100; ++i )
      {
        int     x = 1 + rand() % 30;
        int     y = 1 + rand() % 22;

        if ( !m_Level.TileSet( x, y ) )
        {
          m_Level.AddUnit( pEmerald, x * 32 + 16, y * 32 + 16 );
          pEmerald = NULL;
          break;
        }
      }
      delete pEmerald;

      if ( m_GrowDelay > 1 )
      {
        --m_GrowDelay;
      }
    }
  }
}



void GSGame::UpdateFrame( const float ElapsedTime )
{
  m_Level.Update( ElapsedTime );

  if ( m_Level.NumEmeralds >= 10 )
  {
    theApp.NextState( new GSDone() );
    return;
  }

  if ( m_Level.pPlayer == NULL )
  {
    if ( ( theApp.m_KeyPressed[VK_SPACE] )
    &&   ( theApp.m_KeyReleased[VK_SPACE] ) )
    {
      m_LastScore = m_Level.Score;
      theApp.m_KeyReleased[VK_SPACE] = false;
      RestartGame();
      return;
    }
    if ( ( theApp.m_KeyPressed['X'] )
    &&   ( theApp.m_KeyReleased['X'] ) )
    {
      m_LastScore = m_Level.Score;
      theApp.m_KeyReleased['X'] = false;
      RestartGame();
      return;
    }
  }
}



void GSGame::OnMouse( int X, int Y, int Buttons )
{

}



void GSGame::OnChar( int iChar )
{
  if ( iChar == 27 )
  {
    theApp.NextState( new GSMenu() );
  }
}



void GSGame::OnKeyDown( int iChar )
{

}