#include "global.h"
#include "stdlib.h"
/*
-----------------------------------------------------------------------------
 Class: ScreenHowToPlay

 Desc: See header.

 Copyright (c) 2001-2002 by the person(s) listed below.  All rights reserved.
	Chris Danford
-----------------------------------------------------------------------------
*/

#include "ScreenHowToPlay.h"
#include "ThemeManager.h"
#include "GameState.h"
#include "GameDef.h"
#include "RageLog.h"
#include "RageDisplay.h"
#include "SongManager.h"
#include "NoteFieldPositioning.h"
#include "GameManager.h"

#define SONG_BPM							THEME->GetMetricF("ScreenHowToPlay","SongBPM")
#define SECONDS_TO_SHOW						THEME->GetMetricF("ScreenHowToPlay","SecondsToShow")
#define NUM_PERFECTS						THEME->GetMetricI("ScreenHowToPlay","NumPerfects")
#define NUM_MISSES							THEME->GetMetricI("ScreenHowToPlay","NumMisses")
#define LIFEBARONCOMMAND					THEME->GetMetric ("ScreenHowToPlay","LifeMeterBarOnCommand")
#define USECHARACTER						THEME->GetMetricB("ScreenHowToPlay","UseCharacter")
#define CHARACTERONCOMMAND					THEME->GetMetric ("ScreenHowToPlay","CharacterOnCommand")
#define USEPAD								THEME->GetMetricB("ScreenHowToPlay","UsePad")
#define PADONCOMMAND						THEME->GetMetric ("ScreenHowToPlay","PadOnCommand")
#define PLAYERX								THEME->GetMetricF("ScreenHowToPlay","PlayerX")

ScreenHowToPlay::ScreenHowToPlay() : ScreenAttract("ScreenHowToPlay")
{
	m_In.Load( THEME->GetPathToB("ScreenHowToPlay in") );
	m_In.StartTransitioning();

	m_Out.Load( THEME->GetPathToB("ScreenHowToPlay out") );

	m_Overlay.LoadFromAniDir( THEME->GetPathToB("ScreenHowToPlay overlay") );
	this->AddChild( &m_Overlay );

	switch(GAMESTATE->m_CurGame) // which style should we use to demonstrate?
	{
		case GAME_DANCE:	GAMESTATE->m_CurStyle = STYLE_DANCE_SINGLE;		break;
		case GAME_PUMP:		GAMESTATE->m_CurStyle = STYLE_PUMP_SINGLE;		break;
		case GAME_EZ2:		GAMESTATE->m_CurStyle = STYLE_EZ2_SINGLE;		break;
		case GAME_PARA:		GAMESTATE->m_CurStyle = STYLE_PARA_SINGLE;		break;
		case GAME_DS3DDX:	GAMESTATE->m_CurStyle = STYLE_DS3DDX_SINGLE;	break;
		case GAME_BM:		GAMESTATE->m_CurStyle = STYLE_BM_SINGLE;		break;
		case GAME_MANIAX:	GAMESTATE->m_CurStyle = STYLE_MANIAX_SINGLE;	break;
		default: ASSERT(0); // we should cover all gametypes....
	}

	StepsType nt = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
	int iNumOfTracks = GAMEMAN->NotesTypeToNumTracks( nt );

	ASSERT(iNumOfTracks > 0); // crazy to have less than 1 track....

	m_LifeMeterBar.Load( PLAYER_1 );
	m_LifeMeterBar.Command( LIFEBARONCOMMAND );
	m_LifeMeterBar.FillForHowToPlay( NUM_PERFECTS, NUM_MISSES );

	m_bUsingPad = (USEPAD && DoesFileExist("Characters" SLASH "DancePad-DDR.txt"));

	if( m_bUsingPad )
	{
		m_mDancePad.LoadMilkshapeAscii("Characters" SLASH "DancePad-DDR.txt");
		m_mDancePad.SetRotationX( 35 );
		m_mDancePad.Command( PADONCOMMAND );
	}

	// Display random character
	m_bUsingCharacter = (USECHARACTER && GAMESTATE->m_pCharacters.size());
	if( m_bUsingCharacter )
	{
		Character* rndchar = GAMESTATE->GetRandomCharacter();

		m_mCharacter.LoadMilkshapeAscii( rndchar->GetModelPath() );
		m_mCharacter.LoadMilkshapeAsciiBones("howtoplay", rndchar->GetHowToPlayAnimationPath() );
		
		m_mCharacter.SetRotationX( 40 );
		m_mCharacter.Command( CHARACTERONCOMMAND );
	}

	NoteData* pND = new NoteData;
	pND->SetNumTracks( iNumOfTracks );
	/* Old notes.. Until our HowToPlay animation changes, Steps changed.
	pND->SetTapNote( 0, ROWS_PER_BEAT*12, TAP_TAP );
	pND->SetTapNote( 1, ROWS_PER_BEAT*16, TAP_TAP );
	pND->SetTapNote( 2, ROWS_PER_BEAT*20, TAP_TAP );
	pND->SetTapNote( 0, ROWS_PER_BEAT*24, TAP_TAP );
	pND->SetTapNote( 3, ROWS_PER_BEAT*24, TAP_TAP );
	pND->SetTapNote( 0, ROWS_PER_BEAT*28, TAP_TAP );
	pND->AddHoldNote( HoldNote(2, 32, 35) );
	pND->AddHoldNote( HoldNote(0, 36, 39) );
	pND->AddHoldNote( HoldNote(3, 36, 39) );
	pND->AddHoldNote( HoldNote(2, 40, 43) );
	pND->SetTapNote( 0, ROWS_PER_BEAT*44,    TAP_TAP );
	pND->SetTapNote( 1, (int)(ROWS_PER_BEAT*44.5f), TAP_TAP );
	pND->SetTapNote( 2, ROWS_PER_BEAT*45,    TAP_TAP );
	pND->SetTapNote( 3, (int)(ROWS_PER_BEAT*45.5f), TAP_TAP );
	pND->SetTapNote( 0, ROWS_PER_BEAT*46,    TAP_TAP );
	pND->SetTapNote( 2, ROWS_PER_BEAT*46,    TAP_TAP );
	*/

	pND->SetTapNote( 1, ROWS_PER_BEAT*16, TAP_TAP );
	pND->SetTapNote( 2, ROWS_PER_BEAT*18, TAP_TAP );
	pND->SetTapNote( 0, ROWS_PER_BEAT*20, TAP_TAP );
	pND->SetTapNote( 0, ROWS_PER_BEAT*22, TAP_TAP );
	pND->SetTapNote( 3, ROWS_PER_BEAT*22, TAP_TAP );
	//Misses
	pND->SetTapNote( 0, (int)(ROWS_PER_BEAT*24.0f), TAP_TAP );
	pND->SetTapNote( 1, (int)(ROWS_PER_BEAT*24.1f), TAP_TAP );
	pND->SetTapNote( 3, (int)(ROWS_PER_BEAT*24.2f), TAP_TAP );
	pND->SetTapNote( 1, (int)(ROWS_PER_BEAT*24.3f), TAP_TAP );
	pND->SetTapNote( 2, (int)(ROWS_PER_BEAT*24.4f), TAP_TAP );
	pND->SetTapNote( 0, (int)(ROWS_PER_BEAT*24.5f), TAP_TAP );

	m_pSong = new Song;
	float fSongBPM = SONG_BPM;	// need this on a separate line, otherwise VC6 release build screws up and returns 0
	m_pSong->AddBPMSegment( BPMSegment(0.0,fSongBPM) );
	/* Same as above
	m_pSong->AddStopSegment( StopSegment(12,2) );
	m_pSong->AddStopSegment( StopSegment(16,2) );
	m_pSong->AddStopSegment( StopSegment(20,2) );
	m_pSong->AddStopSegment( StopSegment(24,2) );
	m_pSong->AddStopSegment( StopSegment(28,2) );
	*/
	m_pSong->AddStopSegment( StopSegment(16,2) );
	m_pSong->AddStopSegment( StopSegment(18,2) );
	m_pSong->AddStopSegment( StopSegment(20,2) );
	m_pSong->AddStopSegment( StopSegment(22,2) );

	GAMESTATE->m_pCurSong = m_pSong;
	GAMESTATE->m_bPastHereWeGo = true;
	GAMESTATE->m_PlayerController[PLAYER_1] = PC_AUTOPLAY;

	m_Player.Load( PLAYER_1, pND, &m_LifeMeterBar, NULL, NULL, NULL, NULL, NULL );
	m_Player.SetX( PLAYERX );

	// Don't show judgement
	GAMESTATE->m_PlayerOptions[PLAYER_1].m_fBlind = 1;
	GAMESTATE->m_MasterPlayerNumber = PLAYER_1;
	GAMESTATE->m_bDemonstrationOrJukebox = true;
	this->AddChild( &m_Player );
	this->AddChild( &m_LifeMeterBar );
	delete pND;

	m_fFakeSecondsIntoSong = 0;
	this->ClearMessageQueue();
	this->PostScreenMessage( SM_BeginFadingOut, SECONDS_TO_SHOW );

	this->MoveToTail( &m_Overlay );
	this->MoveToTail( &m_In );
	this->MoveToTail( &m_Out );
}

ScreenHowToPlay::~ScreenHowToPlay()
{
	delete m_pSong;
}

void ScreenHowToPlay::Update( float fDelta )
{
	if(GAMESTATE->m_pCurSong != NULL)
	{
		float rate = 1;

		GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong );
		m_fFakeSecondsIntoSong += fDelta;

		// we want misses from beat 22.8 on out, so change to a HUMAN controller.
		// since we aren't taking input from the user, the steps are always missed.
		if(GAMESTATE->m_fSongBeat > 22.8f)
			GAMESTATE->m_PlayerController[PLAYER_1] = PC_HUMAN;

		if ( m_bUsingCharacter )
		{
			if( GAMESTATE->m_bFreeze )
			{
				switch(int(GAMESTATE->m_fSongBeat))
				{
				case 16: m_mCharacter.SetFrame(30); break;
				case 18: m_mCharacter.SetFrame(85); break;
				case 20: m_mCharacter.SetFrame(150); break;
				case 22: m_mCharacter.SetFrame(270); break;
				};
				rate = 0;
			}
			else
			{
				/* HowToPlay animations.. This will be retimed soon to be a reasonable speed.
				   This was just a quick'n'dirty way of showing this screen correctly. */
				// Until we get a better HowToPlay animation done, it has to be this way..
				if( (GAMESTATE->m_fSongBeat >= 15.0f && GAMESTATE->m_fSongBeat <= 15.2f) )
				{
					m_mCharacter.SetFrame(1);
				}
				if( (GAMESTATE->m_fSongBeat >= 17.0f && GAMESTATE->m_fSongBeat <= 17.2f) )
				{ 
					m_mCharacter.SetFrame(55);
				}
				if( (GAMESTATE->m_fSongBeat >= 19.0f && GAMESTATE->m_fSongBeat <= 19.2f) )
				{ 
					m_mCharacter.SetFrame(120);
				}
				if( (GAMESTATE->m_fSongBeat >= 21.0f && GAMESTATE->m_fSongBeat <= 21.2f) )
				{ 
					m_mCharacter.SetFrame(240);
				}
				// ----------------------------------------------------------------------- */

				if( (GAMESTATE->m_fSongBeat >= 0.0f && GAMESTATE->m_fSongBeat <= 15.0f) ||
					(GAMESTATE->m_fSongBeat >= 16.8f && GAMESTATE->m_fSongBeat <= 17.0f) ||
					(GAMESTATE->m_fSongBeat >= 18.8f && GAMESTATE->m_fSongBeat <= 19.0f) ||
					(GAMESTATE->m_fSongBeat >= 20.8f && GAMESTATE->m_fSongBeat <= 21.0f) ||
					(GAMESTATE->m_fSongBeat >= 22.8f) )
				{
					if( (m_mCharacter.GetCurFrame() >=243) || (m_mCharacter.GetCurFrame() <=184) )
						m_mCharacter.SetFrame(184);
					//Loop for HowToPlay static movement is 184~243
				} else
					// if we update at normal speed during a step animation, it is too slow and
					// doesn't finish in time.
					rate = 1.8f;
			}

			m_mCharacter.Update( fDelta * rate );
		}
	}

	if( m_bUsingPad )
		m_mDancePad.Update( fDelta );

	ScreenAttract::Update( fDelta );
}

void ScreenHowToPlay::HandleScreenMessage( const ScreenMessage SM )
{
	switch( SM )
	{
	case SM_GoToNextScreen:
		GAMESTATE->Reset();
		break;
	}
	ScreenAttract::HandleScreenMessage( SM );
}

void ScreenHowToPlay::DrawPrimitives()
{
	Screen::DrawPrimitives();

	if( m_bUsingPad || m_bUsingCharacter )
	{
		DISPLAY->SetLighting( true );
		DISPLAY->SetLightDirectional( 
			0, 
			RageColor(0.5,0.5,0.5,1), 
			RageColor(1,1,1,1),
			RageColor(0,0,0,1),
			RageVector3(0, 0, 1) );

		if( m_bUsingCharacter )
			m_mCharacter.Draw();
		if( m_bUsingPad )
			m_mDancePad.Draw();

		DISPLAY->SetLightOff( 0 );
		DISPLAY->SetLighting( false );
	}

	m_Overlay.DrawPrimitives();
	m_In.DrawPrimitives();
	m_Out.DrawPrimitives();
}
