#include <Gos2\Gos.h>
#include "d3dx8.h"

static const vertPairs = 50;

struct MyVertex	// the kind of vertex this app uses
{
	D3DXVECTOR3	position;
	D3DXVECTOR3	normal;
	float u,v;
	enum { VertexType = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 };
};

class LightApp : public GosApp
{
public:
	// Functions which the app must provide
	virtual bool	Initialize( _TCHAR *pCommandLine );			// Initialize the application's state
	virtual void	Render();				// Render a single frame
	virtual bool	Step();					// Move the scene forward one frame
	virtual void	Shutdown();				// Called at game shutdown time
	virtual TCHAR	*Name();				// Name of the game

	virtual void	PreferredDisplay( int &Windowed, unsigned int &Width, unsigned int &Height, D3DFORMAT &Format );

	// The following is specific to this app
	D3DMATERIAL8	m_Material;
	D3DLIGHT8		m_Light;
	D3DXMATRIX		m_WorldMatrix;
	D3DXMATRIX		m_ViewMatrix;
	D3DXMATRIX		m_ProjectionMatrix;
	MyVertex		m_aVertex[vertPairs*2];
	GosTexture *	m_pTexture;
	GosVertexBuffer*m_pVertexBuffer;
	GosSurface *	m_pCursorImage;
	DWORD			m_bgColor;
};

LightApp myApp;	// *The* Application

void LightApp::PreferredDisplay( int &Windowed, unsigned int &Width, unsigned int &Height, D3DFORMAT &Format )
{
#if 0
	Windowed = false;
#else
	Windowed = true;
#endif
	Width = 640;
	Height = 480;
}

bool LightApp::Initialize( _TCHAR *pCommandLine )
{

	// Set up a material to use
	D3DCOLORVALUE yellow = { 1.f, 1.f, 0.f, 1.f };
	ZeroMemory( &m_Material, sizeof(m_Material) );
	m_Material.Diffuse = yellow;
	m_Material.Ambient = yellow;

	// Set up a directional light
	D3DCOLORVALUE white = { 1.f, 1.f, 1.f, 1.f };
	ZeroMemory( &m_Light, sizeof(m_Light) );
	m_Light.Type = D3DLIGHT_DIRECTIONAL;
	m_Light.Diffuse = white;
	m_Light.Range = 1000.f;

	// Initialize matrices ( m_WorldMatrix is set each frame )
	D3DXMatrixLookAtLH( &m_ViewMatrix, &D3DXVECTOR3( 0.f, 3.f, -5.f ),
		&D3DXVECTOR3( 0.f, 0.f, 0.f ), &D3DXVECTOR3( 0.f, 1.f, 0.f ) );
	D3DXMatrixPerspectiveFovLH( &m_ProjectionMatrix, D3DX_PI/4, 1.f, 1.f, 100.f );

	// Initialize the vertices
	for( int pair = 0; pair < vertPairs; pair++ )
	{
		float sinVal = sinf(( 2.f * D3DX_PI * pair ) / ( vertPairs - 1 ));
		float cosVal = cosf(( 2.f * D3DX_PI * pair ) / ( vertPairs - 1 ));
		m_aVertex[pair*2].position = D3DXVECTOR3( sinVal, -1.f, cosVal );
		m_aVertex[pair*2].normal = D3DXVECTOR3( sinVal, 0, cosVal );
		m_aVertex[pair*2].u = (float)pair / (float)(vertPairs-1);
		m_aVertex[pair*2].v = 0.f;
		m_aVertex[pair*2+1].position = D3DXVECTOR3( sinVal, 1.f, cosVal );
		m_aVertex[pair*2+1].normal = D3DXVECTOR3( sinVal, 0, cosVal );
		m_aVertex[pair*2+1].u = (float)pair / (float)(vertPairs-1);
		m_aVertex[pair*2+1].v = 1.f;
	}

	// Create a vertex buffer
	m_pVertexBuffer = GosVertexBuffer::CreateFromMemory(m_aVertex,sizeof(m_aVertex),MyVertex::VertexType,0);

	// Load a texture from a disk file
	m_pTexture = GosTexture::CreateFromFile( _T("assets\\Graphics\\wall.bmp") );

	// Set up an image for a cursor
	m_pCursorImage = GosSurface::CreateEmpty(64,64,D3DFMT_A8R8G8B8);
	m_pCursorImage->LoadFromFile( _T("assets\\Graphics\\ActivePointer.TGA") );

	Gos3D::SetCursorProperties( 0, 0, m_pCursorImage );
	Gos3D::ShowCursor( true );

	return true;	// true means the initialize succeeded
}

bool LightApp::Step()
{
	float rotation = GosUtil::Time_mS() / 300.f;

	// Set the light direction & world rotation
	m_Light.Direction.x = sinf(rotation);
	m_Light.Direction.z = cosf(rotation);
	D3DXMatrixIdentity( &m_WorldMatrix );
	D3DXMatrixRotationX( &m_WorldMatrix, rotation );
//	Gos3D::SetCursorPosition( (int)(sinf(rotation*2) * 300.f + 350.f), (int)(cosf(rotation) * 300.f + 350.f), 0 );

	long x,y;
	DWORD buttons;
	GosUser::GetStatus( &buttons, &x, &y );
	Gos3D::SetCursorPosition( (x*Gos3D::Width())>>16, (y*Gos3D::Height())>>16, 0 );
	m_bgColor = 0;
	m_bgColor |= ( ( buttons >> 0 ) & 0x000f ) << 4;
	m_bgColor |= ( ( buttons >> 4 ) & 0x000f ) << 12;
	m_bgColor |= ( ( buttons >> 8 ) & 0x000f ) << 20;
	
	return true;	// true means keep going
}

void LightApp::Render()
{
	// Clear the background to blue and begin the scene
	Gos3D::Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, m_bgColor, 1.0f, 0L );
	Gos3D::BeginScene();

	// Set material, lighting, and rendering conditions
	Gos3D::SetMaterial( &m_Material );
	Gos3D::SetLight( 0, &m_Light );
	Gos3D::LightEnable( 0, true );
	Gos3D::SetRenderState( D3DRS_LIGHTING, true );
	Gos3D::SetRenderState( D3DRS_AMBIENT, 0x00202020 );
	Gos3D::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
	Gos3D::SetRenderState( D3DRS_ZENABLE, true );

	// Set texturing
	Gos3D::SetTexture( 0, m_pTexture );
	Gos3D::SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );

	// Set matrices
	Gos3D::SetTransform( D3DTS_VIEW, &m_ViewMatrix );
	Gos3D::SetTransform( D3DTS_WORLD, &m_WorldMatrix );
	Gos3D::SetTransform( D3DTS_PROJECTION, &m_ProjectionMatrix );

	// Draw the object
	Gos3D::SetFVFShader( MyVertex.VertexType );
	// Gos3D::DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2*vertPairs-2, (void *)m_aVertex, sizeof(MyVertex) );
	Gos3D::SetStreamSource(0,m_pVertexBuffer,sizeof(MyVertex));
	Gos3D::DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2*vertPairs-2);

	// Done rendering, end the scene
	Gos3D::EndScene();
}

void LightApp::Shutdown()
{
	delete m_pTexture;
	delete m_pVertexBuffer;
	delete m_pCursorImage;
}

TCHAR *LightApp::Name()
{
	return _T("Light Application");
}