/** 
 * \file Movie.cpp
 * \brief Contains CMovie class functions implementation for playing scripted animations.
 * 
 * Movies will be played in 'engine' of the game. They will be scripted in txt files.
 * This module would read given movie script from the file and play it.
 * Game movies can be played between levels to explain/amuse/relax/and mostly explain whats happening.
 * \author Petar Bajic, MPE (C) All Rights Reserved, Homepage: www.mystic-peanut.com
 * \date January, 16 2007.
 */

#include "Movie.h"
#include "Terrain.h"
#include "Language.h"

/**
 * \brief Standard constructor.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CMovie::CMovie()
{
	/*MIDI NOT USED BUT WE SAVE CODE FOR LATER
	m_pPerformance = NULL;
	m_pLoader = NULL;
	m_pSegment = NULL;*/
	m_movieTheme = NULL;
	m_textureBlack = NULL;
	m_sprite = NULL;
	m_pFont = NULL;
	m_pFontBig = NULL;
	m_Language = NULL;
	m_pTerrain = NULL;
	m_pTurtle = NULL;
	m_pSheep = NULL;
	m_screenWidth = 700;
	m_screenHeight = 550;
	m_MovieTime = 0.0f;
	m_textPos=D3DXVECTOR2(0.0f,0.0f);
}

/**
 * \brief Standard Destructor.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CMovie::~CMovie()
{
	/*MIDI NOT USED BUT WE SAVE CODE FOR LATER
	if (m_pPerformance)
	{
		m_pPerformance->Stop(NULL,NULL,0,0);
		m_pPerformance->CloseDown();
		m_pPerformance->Release();
	}
	if (m_pLoader)
		m_pLoader->Release(); 
	if (m_pSegment)
		m_pSegment->Release();*/

	SAFE_RELEASE(m_sprite);
	SAFE_RELEASE(m_pFont);
	SAFE_RELEASE(m_pFontBig);
	SAFE_RELEASE(m_textureBlack);
	delete m_movieTheme;
}

/**
 * \brief OnLost device releases POOL objects.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CMovie::OnLostDevice()
{
	m_sprite->OnLostDevice();
	m_pFont->OnLostDevice();
	m_pFontBig->OnLostDevice();
	//m_pTerrain->OnLostDevice(); //Done in Level.cpp
}

/**
 * \brief Resets sprites, fonts and particles.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CMovie::OnResetDevice(LPDIRECT3DDEVICE9 pd3dDevice, int screenWidth, int screenHeight)
{
	m_sprite->OnResetDevice();
	m_pFont->OnResetDevice();
	m_pFontBig->OnResetDevice();
	//m_pTerrain->OnResetDevice(pd3dDevice); //Already Done in Level.cpp!!!!!!!! (((that was hard bug to find!!!)))
	m_screenWidth = (float)screenWidth;
	m_screenHeight = (float)screenHeight;
}

/**
 * \brief Init movie with terrain, turtle, sheep and language objects.
 * This function loads music and prepares sprites and fonts for text drawing.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool CMovie::Init(HWND hWnd, LPDIRECT3DDEVICE9 pd3dDevice, int screenWidth, int screenHeight, CTerrain* pTerrain, CTurtle* pTurtle, CSheep* pSheep, CLanguage* language)
{
	/*MIDI NOT USED BUT WE SAVE CODE FOR LATER
	CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8,(void**)&m_pLoader);
	CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance8,(void**)&m_pPerformance );
	m_pPerformance->InitAudio(NULL,NULL,NULL,DMUS_APATH_SHARED_STEREOPLUSREVERB,64,DMUS_AUDIOF_ALL,NULL);*/
	
	//play music
	m_movieTheme = new CMedia();
	if (!(m_movieTheme->Init(hWnd, L"Media/Music/movietheme.mp3")))
	{
		MessageBox(NULL,L"Could not load Media/Music/movietheme.mp3 file",L"Error",MB_OK);
		return false;
	}

	m_screenWidth = (float)screenWidth;
	m_screenHeight = (float)screenHeight;

	m_Language = language;

	/*MIDI NOT USED BUT WE SAVE CODE FOR LATER
	LPWSTR wstrFileName = L"Media\\Music\\movie.mid";
	if (FAILED(m_pLoader->LoadObjectFromFile(CLSID_DirectMusicSegment,IID_IDirectMusicSegment8,wstrFileName,(LPVOID*) &m_pSegment)))
	{
		MessageBox( NULL, L"Music file 'movie.mid' not found. Program will exit.", L"Turtle Shepherd", MB_OK );
		m_pPerformance->CloseDown();
		m_pLoader->Release();
		m_pPerformance->Release();
		CoUninitialize();
		return false;
	}
	m_pSegment->Download( m_pPerformance );*/

	if (FAILED(D3DXCreateFont(pd3dDevice,30, 0, 0, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Georgia",&m_pFont)))
		return false;
	if (FAILED(D3DXCreateFont(pd3dDevice,45, 0, 0, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Georgia",&m_pFontBig)))
		return false;
	if (FAILED(D3DXCreateSprite(pd3dDevice,&m_sprite)))
		return false;
	if (FAILED(D3DXCreateTextureFromFile(pd3dDevice,L"Media/Pics/black.png", &m_textureBlack )))
		return false;

	//Fetch preloaded models
	m_pTerrain = pTerrain;
	m_pTurtle = pTurtle;
	m_pSheep = pSheep;

	m_vEye	=D3DXVECTOR3( 40.0f, 105.0f, -15.0f);
	m_vAt   =D3DXVECTOR3( 40.0f, 120.0f, 100.0f);
	m_vUp   =D3DXVECTOR3( 0.0f, 1.0f, 0.0f );

	return true;
}

/**
 * \brief Movie quits on any user action so not much event handling.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool CMovie::OnEvent(LPDIRECT3DDEVICE9 pd3dDevice, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, int* code)
{
	// Current mouse position
	int iMouseX = (int)LOWORD(lParam);
	int iMouseY = (int)HIWORD(lParam);

    switch( msg )
    {
		//These were used to position camera while testing
		case WM_KEYDOWN:
		{
			if(wParam == VK_PRIOR)
			{
				m_vEye.y += 1.0f;
				m_vAt.y += 1.0f;
				return true;
			}
			if(wParam == VK_NEXT)
			{
				m_vEye.y -= 1.0f;
				m_vAt.y -= 1.0f;
				return true;
			}
			if(wParam == VK_LEFT)
			{
				m_vEye.x -= 1.0f;
				m_vAt.x -= 1.0f;
				return true;
			}
			if(wParam == VK_RIGHT)
			{
				m_vEye.x += 1.0f;
				m_vAt.x += 1.0f;
				return true;
			}
			if(wParam == VK_UP)
			{
				m_vEye.z -= 1.0f;
				m_vAt.z -= 1.0f;
				return true;
			}
			if(wParam == VK_DOWN)
			{
				m_vEye.z += 1.0f;
				m_vAt.z += 1.0f;
				return true;
			}
		}
		case WM_LBUTTONDOWN:
		{
		}
		case WM_MOUSEMOVE:
		{
		}
	}

	return false;
}

/**
 * \brief Stops movie music.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CMovie::stopMovie()
{
	/*MIDI NOT USED BUT WE SAVE CODE FOR LATER
	m_pPerformance->Stop(NULL,NULL,0,0);*/
	m_movieTheme->Stop();
}

/**
 * \brief Starts movie, plays music, resets models position, camera position and text position.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CMovie::playMovie()
{
	/*MIDI NOT USED BUT WE SAVE CODE FOR LATER
	m_pPerformance->PlaySegmentEx(m_pSegment,NULL,NULL,0,0,NULL,NULL,NULL);*/
	m_vEye	=D3DXVECTOR3( 40.0f, 105.0f, -15.0f);
	m_vAt   =D3DXVECTOR3( 40.0f, 120.0f, 100.0f);
	m_vUp   =D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
	m_textPos=D3DXVECTOR2(0.0f,0.0f);
	m_MovieTime = 0.0f;
	m_movieTheme->Play();
	m_movieTheme->SetLoop();
	m_Blinking = false;
	m_pSheep->m_Position.x = 0.0f;
	m_pSheep->m_Position.y = 0.3f;
	m_pSheep->m_Position.z = -38.0f;
	m_pSheep->m_Alive = true;
	m_pSheep->m_BeingCarriedAway = false;
	m_pSheep->m_Moved = false;
	m_pSheep->m_Facing = D3DX_PI/2;
	m_pTurtle->m_Position.x = 2.0f;
	m_pTurtle->m_Position.y = 0.0f;
	m_pTurtle->m_Position.z = -44.0f;
	m_pTurtle->m_Facing = 0.0f;
}

/**
 * \brief Renders movie. Terrain, models, sprites, text.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CMovie::OnRender(LPDIRECT3DDEVICE9 pd3dDevice)
{
	D3DXMATRIX mat;
	D3DXVECTOR2 spriteCentre=D3DXVECTOR2(m_screenWidth/2,50.0f);
	D3DXVECTOR2 scaling=D3DXVECTOR2(1.0f,1.0f);
	float rotation=0; //timeGetTime()/500.0f;
	D3DXVECTOR2 trans=D3DXVECTOR2((float)m_screenWidth - 550,(float)(m_screenHeight - 200));
	D3DXVECTOR2 transBlack=D3DXVECTOR2(0.0f,-130.0f);
	RECT rect;
	rect.top = 0;
	rect.bottom = 600;
	rect.left = 0;
	rect.right = 550;

	//Render Terrain
	m_pTerrain->OnRender(pd3dDevice, true);
	//Render Turtle
	m_pTurtle->OnRender(pd3dDevice);
	//Render Sheep
	m_pSheep->OnRender(pd3dDevice);

	//Render sprites
	pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	m_sprite->Begin(D3DXSPRITE_ALPHABLEND);

	//Render Text
	trans.y += m_textPos.y;
	my_DrawOutlineText(&mat,&scaling,&spriteCentre,rotation,&trans,m_sprite, m_pFont, m_Language->GetText(MPE_TEXT_MOVIE_TEXT1), &rect, 0xFFFFFF00, 0xFF000000);
	trans.y += 350;
	my_DrawOutlineText(&mat,&scaling,&spriteCentre,rotation,&trans,m_sprite, m_pFont, m_Language->GetText(MPE_TEXT_MOVIE_TEXT2), &rect, 0xFFFFFF00, 0xFF000000);
	trans.y += 265;
	my_DrawOutlineText(&mat,&scaling,&spriteCentre,rotation,&trans,m_sprite, m_pFont, m_Language->GetText(MPE_TEXT_MOVIE_TEXT3), &rect, 0xFFFFFF00, 0xFF000000);
	trans.y += 45;
	if(m_Blinking)
	{
		my_DrawOutlineText(&mat,&scaling,&spriteCentre,rotation,&trans,m_sprite, m_pFont, m_Language->GetText(MPE_TEXT_LEVEL_PRESS_SPACE), &rect, 0xFFFFFF00, 0xFF000000);
	}

	//Render black surfaces above and below
	if (m_screenWidth > 100) //100 is width of this picture
		scaling.x = m_screenWidth/100;
	transBlack.y += m_screenHeight/10 - 50;
	my_DrawSprite(&mat, &scaling, &spriteCentre, rotation, &transBlack, m_textureBlack, m_sprite, true, NULL, NULL, NULL, NULL);
	rotation=D3DX_PI;
	transBlack.y =m_screenHeight + 20;
	transBlack.y -= m_screenHeight/10 - 50;
	my_DrawSprite(&mat, &scaling, &spriteCentre, rotation, &transBlack, m_textureBlack, m_sprite, true, NULL, NULL, NULL, NULL);

	m_sprite->End();
	pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
}

/**
 * \brief Animates movie. Everything is hardcoded here, camera movement, model animation, text sliding...
 * 
 * It would be wonderful for movie class to use some kind of script file which would define all movements.
 * That way same class could be used for multiple movies, you just make new instance of CMovie and pass sript file to it.
 * Problem is making such script file and parsing it commonly for various movies?
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CMovie::OnFrameMove(LPDIRECT3DDEVICE9 pd3dDevice, double fTime, float fElapsedTime)
{
	D3DXMATRIX matView;
	LONGLONG end, current;
	m_MovieTime += fElapsedTime;

	///LOOp music (NOT FRIKING WORKING! MAY THE ALL MIGHTY SMITE THOSE WHO MAKE SOUND PLAYING API WITHOUT LOOPING)
	m_movieTheme->m_mediaSeeking->GetDuration(&end);
	m_movieTheme->m_mediaSeeking->GetCurrentPosition(&current);
	if(current >= end)
		m_movieTheme->m_mediaSeeking->SetPositions(&(m_movieTheme->m_begin),AM_SEEKING_AbsolutePositioning,0,0);


	//Move terrain (obsolete if scenography is completely static)
	m_pTerrain->OnFrameMove(pd3dDevice,fTime,fElapsedTime,true);

	////Position view matrix (camera)
	if ((m_MovieTime > 2.4f) && (m_MovieTime < 50.0f))
	{
		if (m_vEye.y > 5)
			m_vEye.y -=fElapsedTime*2;
		if (m_vAt.y > -15)
			m_vAt.y -=fElapsedTime*3;
		m_vEye.z -= fElapsedTime;
		m_vEye.x -= fElapsedTime;
	}
	
	//Slide text up the screen by reducing its y coordinate as time goes by.
	if (m_MovieTime < 63.0f)
	{
		m_textPos.y -= fElapsedTime*12;
	}

	//Blink "PRESS SPACE TO CONTINUE" text
	if (((int)m_MovieTime%2)>0)
		m_Blinking = true;
	else
		m_Blinking = false;

	//Animate sheep and turtle walking, and then animate them idle.
	if(m_MovieTime > 48.0f)
	{
		if (m_MovieTime < 69.0f)
		{
			m_pSheep->m_Model->SetAnimationSet(1);
			m_pTurtle->m_Model->SetAnimationSet(2);
			m_pSheep->m_Position.z += fElapsedTime*2;
			m_pTurtle->m_Position.z += fElapsedTime*2;
		}
		else
		{
			m_pSheep->m_Model->SetAnimationSet(0);
			m_pTurtle->m_Model->SetAnimationSet(0);
		}
	}

	//Set camera position and direction
	D3DXMatrixLookAtLH( &matView, &m_vEye, &m_vAt, &m_vUp );
	pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

	//Move Turtle and Sheep

	//World Matrix cinculation
	D3DXMATRIXA16 matWorld,matTrans;
	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixRotationY( &matWorld, m_pTurtle->m_Facing + D3DX_PI);//we add + D3DX_PI cause model is rotated oposite
	D3DXMatrixTranslation( &matTrans, m_pTurtle->m_Position.x, m_pTurtle->m_Position.y, m_pTurtle->m_Position.z );
	D3DXMatrixMultiply(&matWorld, &matWorld, &matTrans);

	//Call OnFrameMove on turtle after view matrix is calculated to avoid strange glitches
	m_pTurtle->OnFrameMove(pd3dDevice, fElapsedTime, &matWorld);	

	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixRotationY(&matWorld, m_pSheep->m_Facing);
	D3DXMatrixTranslation( &matTrans, m_pSheep->m_Position.x, m_pSheep->m_Position.y+2, m_pSheep->m_Position.z );
	D3DXMatrixMultiply(&matWorld, &matWorld, &matTrans);
	pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
	m_pSheep->OnFrameMove(pd3dDevice, fElapsedTime, &matWorld);

}
