#include "StdAfx.h"
#include "GameDemoEngine.h"
#include "3DObject.h"

CGameDemoEngine::CGameDemoEngine(CDirect3D *d3d):
	g_Cursor(NULL),
	g_CursorTexture(NULL),
	g_pDI(NULL),
	g_pKeyboard(NULL),
	Fighter(NULL),
	Camera(NULL),
	Ground(NULL),
	Explosion(NULL)
{
	this->d3d = d3d;
	StartGame();
	//Preparing mouse cursor sprite
	loadTexture(d3d);
	D3DXCreateSprite( d3d->g_pd3dDevice, &g_Cursor );
    
    DWORD   dwCoopFlags;
	dwCoopFlags = DISCL_NONEXCLUSIVE |  DISCL_FOREGROUND;
	if( FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
                                  IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
        exit(-1);
    
    if( FAILED(g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL ) ) )
        exit(-1);

	if( FAILED(g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
        exit(-1);

	g_pKeyboard->SetCooperativeLevel( d3d->hWnd, dwCoopFlags );
    
		DIPROPDWORD dipdw;
        dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
        dipdw.diph.dwObj        = 0;
        dipdw.diph.dwHow        = DIPH_DEVICE;
        dipdw.dwData            = SAMPLE_BUFFER_SIZE; 

    if( FAILED( g_pKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
            exit(-1);
    // Acquire the newly created device
    g_pKeyboard->Acquire();
	SetTimer( d3d->hWnd, IDT_KeyboardTimer, 1000 / 100, (TIMERPROC)NULL );

    
	d3d->g_pd3dDevice->CreateVertexBuffer( 4*sizeof(Vertex),
									  D3DUSAGE_WRITEONLY, Vertex::FVF,
                                      D3DPOOL_MANAGED, &m_pViewportVB, NULL ); 

    if( m_pViewportVB )
    {
        // Setup dimensions for the viewport covering square
        Vertex* v;
        m_pViewportVB->Lock( 0, 0, (void**)&v, 0 );
        v[0].color = v[1].color = v[2].color = v[3].color = 0xFFFFFFFF;
        v[0].position = D3DXVECTOR3(-1 ,1,0.0f);
        v[0].u = 0.0f;  v[0].v = 0.0f; 
        v[1].position = D3DXVECTOR3(-1,-1,0.0f);
        v[1].u = 0.0f;  v[1].v = 1.0f; 
		v[2].position = D3DXVECTOR3(1, 1,0.0f);
        v[2].u = 1.0f;  v[2].v = 0.0f; 
        v[3].position = D3DXVECTOR3(1, -1,0.0f);
        v[3].u = 1.0f;  v[3].v = 1.0f; 
        m_pViewportVB->Unlock();
    }
}

void CGameDemoEngine::StartGame()
{
	SAFE_DELETE( Fighter );
	SAFE_DELETE( Camera );
	SAFE_DELETE( Ground );
	SAFE_DELETE( Explosion );

	Fighter = new CFighter(d3d);
	Camera = new CCamera();
	Ground = new CGround(d3d, Camera);
	Explosion = new CExplosion(d3d);

    GameState = GS_SPLASH;
}

CGameDemoEngine::~CGameDemoEngine( void )
{
	if( g_Cursor != NULL ) 
        g_Cursor->Release();

	if( g_CursorTexture != NULL ) 
        g_CursorTexture->Release();

	if( g_pKeyboard ) 
        g_pKeyboard->Unacquire();
    
	SAFE_DELETE( Fighter );
	SAFE_DELETE( Camera );
	SAFE_DELETE( Ground );
	SAFE_DELETE( Explosion );
    SAFE_RELEASE( g_pKeyboard );
    SAFE_RELEASE( g_pDI );
}

void CGameDemoEngine::loadTexture( CDirect3D *d3d )
{
	if (!d3d) return;

	D3DXIMAGE_INFO d3dxImageInfo;

	D3DXCreateTextureFromFileEx( d3d->g_pd3dDevice,
                                 "cursor.bmp",
                                 32, 
                                 32, 
                                 1,  
                                 D3DPOOL_DEFAULT,
                                 D3DFMT_UNKNOWN,
                                 D3DPOOL_DEFAULT,
                                 D3DX_DEFAULT,
                                 D3DX_DEFAULT,
                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),
                                 &d3dxImageInfo,
                                 NULL,
                                 &g_CursorTexture );
	D3DXCreateTextureFromFile( d3d->g_pd3dDevice, "Spiral.bmp", &g_pSplashTexture );
	if (!g_pSplashTexture) exit(-1);

    d3d->g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	d3d->g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}

#define KeyState(x) ((diks[x] & 0x80) ? TRUE : FALSE)

HRESULT CGameDemoEngine::ReadKeyboardInput()
{
    DIDEVICEOBJECTDATA didod[ SAMPLE_BUFFER_SIZE ];  
    DWORD              dwElements;
    DWORD              i;
    HRESULT            hr;

    if( NULL == g_pKeyboard ) 
        return S_OK;
/*    
    dwElements = SAMPLE_BUFFER_SIZE;
    hr = g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
                                     didod, &dwElements, 0 );
    if( hr != DI_OK ) 
    {
        hr = g_pKeyboard->Acquire();
        while( hr == DIERR_INPUTLOST ) 
            hr = g_pKeyboard->Acquire();
        return S_OK; 
    }

    for( i = 0; i < dwElements; i++ ) 
    {
		switch(didod[i].dwOfs)
		{
			case DIK_UP: 
				Fighter->Rotate (3.14f / 180.0f,0, 0);
				break;
		}
    }*/

    BYTE    diks[256];
    ZeroMemory( diks, sizeof(diks) );
    hr = g_pKeyboard->GetDeviceState( sizeof(diks), diks );
    if( FAILED(hr) ) 
    {
        hr = g_pKeyboard->Acquire();
        while( hr == DIERR_INPUTLOST ) 
            hr = g_pKeyboard->Acquire();
        return S_OK; 
    }
    
	switch(GameState)
	{
		case GS_FLIGHT:
			if (KeyState(DIK_RIGHT) == TRUE) Fighter->IncreaseRotation();
			if (KeyState(DIK_LEFT) == TRUE) Fighter->DecreaseRotation();
			if (KeyState(DIK_UP) == TRUE) Fighter->DecreaseHeight();
			if (KeyState(DIK_DOWN) == TRUE) Fighter->IncreaseHeight();
			if (KeyState(DIK_Q) == TRUE) Fighter->IncreaseSpeed();
			if (KeyState(DIK_A) == TRUE) Fighter->DecreaseSpeed();
			if (KeyState(DIK_SPACE) == TRUE) Fighter->BeginShot();
			break;
		case GS_STOP:
		
			break;
		case GS_SPLASH:
		    if (KeyState(DIK_SPACE) == TRUE)
			{
				GameState = GS_FLIGHT;
		        Fighter->IncreaseSpeed();
   			    Fighter->IncreaseSpeed();
			}
			break;
	}

	return S_OK;
}


int CGameDemoEngine::ProcessMessage (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
		switch( msg )
	    {
		    case WM_MOUSEMOVE:
				xPos = LOWORD(lParam);
				yPos = HIWORD(lParam);	
				return 1;
			case WM_TIMER:
				{
					if (wParam == IDT_KeyboardTimer)
					{
						ReadKeyboardInput();
						return 1;
					}
				}
			    break;
		}
	return 0;
}

void CGameDemoEngine::RenderScene(CDirect3D *d3d)
{
	
	//Переделать со switch
	//Вычисления
	if (GameState == GS_FLIGHT)
	{
	  Fighter->ComputeModel();
	  Ground->MoveGround(Camera);

	  //Сделать нормально
      //движение земли 
	  Ground->Translate(0,0,-Ground->GetDifference());
	  Fighter->Translate(0,0,-Ground->GetDifference());
	  Fighter->Laser->Translate(0,0,-Ground->GetDifference());
	  Ground->ZeroDifference();

	  //Сброс на 0 позицию
	  double FighterPos = Fighter->GetZPosition();
	  Fighter->Translate (0,0,-FighterPos); 
	  Ground->Translate(0,0,-FighterPos);
	  Fighter->Laser->Translate(0,0,-FighterPos);

	  //Установка камеры
	  Camera->TrackObject (d3d, (ObjectModel *)Fighter);	
 	  
	}
	else
	if (GameState == GS_EXPLODING)
	{
		Explosion->MoveFrame ();
		Camera->TrackObject (d3d, (ObjectModel *)Explosion);	
		if (Explosion->IsFinished()) StartGame();
	}
	
	if (GameState == GS_FLIGHT)
	{
	  if (Ground->ColisionDetection(Fighter))
	  {
	    GameState = GS_EXPLODING;
	    D3DXVECTOR3 pos = Fighter->ObjectCenter();
	    Explosion->Explode (pos.x-1.5,pos.y-1.5,pos.z,3);
	  }
	  else
	  if (Ground->LaserShot(Fighter->Laser))
	  {
		Fighter->EndShot();
	  }
	}

	HRESULT hr;
	if(SUCCEEDED(d3d->g_pd3dDevice->BeginScene()))
	{
		d3d->Clear();
		if (GameState == GS_SPLASH)
			RenderSplash(d3d);
		else
		{
			if (GameState == GS_FLIGHT) Fighter->Render();
			Ground->Render();
			if (GameState == GS_EXPLODING) Explosion->Render();
		}
		
		if (g_Cursor && g_CursorTexture && d3d->Fullscreen)
		{
			//D3DXVECTOR2 vTrans( (FLOAT)xPos, (FLOAT)yPos);
			//g_Cursor->Begin(0); 
			//g_Cursor->Draw(g_CursorTexture,NULL,NULL,&vTrans,0xFFFFFFFF );
			//g_Cursor->End();
		}		    
		// Close the scene.
		hr = d3d->g_pd3dDevice->EndScene(); 
		if(FAILED(hr))
	        return;
	}
	d3d->SwapBuffers();
}

VOID CGameDemoEngine::RenderSplash(CDirect3D *d3d)
{
    D3DXMATRIX idn, matWorld, matProj, matView;
    D3DXMatrixIdentity( &idn );

	d3d->g_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorld );
	d3d->g_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
	d3d->g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &matProj);
	
	d3d->g_pd3dDevice->SetTransform( D3DTS_WORLD, &idn );
	d3d->g_pd3dDevice->SetTransform( D3DTS_VIEW, &idn );
	d3d->g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &idn);

	d3d->g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,     FALSE );
	d3d->g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);

	
		d3d->g_pd3dDevice->SetTexture( 0, g_pSplashTexture );
		d3d->g_pd3dDevice->SetFVF( Vertex::FVF );
        d3d->g_pd3dDevice->SetStreamSource( 0, m_pViewportVB, 0, sizeof(Vertex) );
        d3d->g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0, 2 );
		d3d->g_pd3dDevice->SetTexture(0,0);


	d3d->g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
	d3d->g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
	d3d->g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);

}
