#include "SpriteRenderer.h"
#include "ScreenManager.h"

SpriteRenderer::SpriteRenderer(void)
{
	position = new D3DXVECTOR3( 0.0, 0.0, 1.0 );
    transform = new D3DXMATRIX();
    D3DXMatrixIdentity(transform);
}

SpriteRenderer::~SpriteRenderer(void)
{
	if ( spriteBrush ) {
		spriteBrush->Release();
		spriteBrush = 0;
	}
	if ( position ) {
		delete position;
		position = 0;
	}
	if ( transform ) {
		delete transform;
		transform = 0;
	}
}

HRESULT SpriteRenderer::init( LPDIRECT3DDEVICE9 d3dDevice, TextureManager* newTextureManager, ScreenManager* newScreenManager ) {
	textureManager = newTextureManager;
	screenManager = newScreenManager;

	//Create a Sprite
	HRESULT r = D3DXCreateSprite(d3dDevice, &spriteBrush);
	if (FAILED(r))
	{
		GameError("Error Creating Sprite");
		return r;
	}

	return S_OK;
}

// Draws in screen coordinates for easy background tile drawing
HRESULT SpriteRenderer::renderToScreen( int textureId, int x, int y ) {
	position->x = ( float ) x;
	position->y = ( float ) y;
	HRESULT r = S_OK;

	LPDIRECT3DTEXTURE9 aTexture = textureManager->getTexture( textureId );
	if ( aTexture == NULL ) {
		return E_FAIL;
	}
	r = spriteBrush->Draw( aTexture,
		NULL, //CONST RECT *pSrcRect, //NULL uses the whole texture
		NULL, //CONST D3DXVECTOR3 *pCenter, //NULL uses top left corner as center...
		position, //CONST D3DXVECTOR3 *pPosition, //NULL means no position (0,0,0)
		D3DCOLOR_RGBA(255,255,255,255) //D3DCOLOR Color //MODULATION COLOR (TINTING !! - AND TINTING ALPHA !!)
    );

	if ( FAILED( r ) ) {
		GameError( "Could Not Draw sprite" );
		return r;
	}

	spriteBrush->Flush();
	return S_OK;
}

HRESULT SpriteRenderer::renderTile( TileStamp* aTile ) {
	HRESULT r = S_OK;

	// Get the tiles x and y in world coordinates
	int x = aTile->getTileXOffset() * TILE_WIDTH;
	int y = ( aTile->getTileYOffset() / 2 ) * TILE_HEIGHT;

	if ( aTile->getTileYOffset() % 2 == 1 ) {
		x += ( TILE_WIDTH / 2 );
		y += ( TILE_HEIGHT / 2 );
	}

	// Take into account tallness of tile stamps
	y -= ( aTile->getTotalHeight() - TILE_HEIGHT );
	x -= ( aTile->getTotalWidth() / 2 - 32 );

	// Convert world to screen
	x -= screenManager->getScreenX();
	y -= screenManager->getScreenY();

	// Put into position vector
	position->x = ( float ) x;
	position->y = ( float ) y;

	LPDIRECT3DTEXTURE9 aTexture = textureManager->getTexture( aTile->getTextureId() );
	if ( aTexture == NULL ) {
		return E_FAIL;
	}

	r = spriteBrush->Draw( aTexture,
		NULL, //CONST RECT *pSrcRect, //NULL uses the whole texture
		NULL, //CONST D3DXVECTOR3 *pCenter, //NULL uses top left corner as center...
		position, //CONST D3DXVECTOR3 *pPosition, //NULL means no position (0,0,0)
		D3DCOLOR_RGBA(255,255,255,255) //D3DCOLOR Color //MODULATION COLOR (TINTING !! - AND TINTING ALPHA !!)
    );

	if ( FAILED( r ) ) {
		GameError( "Could Not Draw sprite" );
		return r;
	}

	spriteBrush->Flush();

	return S_OK;
}

HRESULT SpriteRenderer::renderSpriteToScreen( SpriteStamp* aStamp ) {
	HRESULT r = S_OK;

	LPDIRECT3DTEXTURE9 aTexture = textureManager->getTexture( aStamp->getTextureId() );
	if ( aTexture == NULL ) {
		return E_FAIL;
	}
	r = spriteBrush->Draw( aTexture,
		aStamp->getClippingRect(), //CONST RECT *pSrcRect, //NULL uses the whole texture
		aStamp->getCenter(), //CONST D3DXVECTOR3 *pCenter, //NULL uses top left corner as center...
		aStamp->getPosition(), //CONST D3DXVECTOR3 *pPosition, //NULL means no position (0,0,0)
		aStamp->getModulationColor() //D3DCOLOR Color //MODULATION COLOR (TINTING !! - AND TINTING ALPHA !!)
    );

	if ( FAILED( r ) ) {
		GameError( "Could Not Draw sprite" );
		return r;
	}

	spriteBrush->Flush();
	return S_OK;
}

HRESULT SpriteRenderer::renderSpriteToWorld( SpriteStamp* aStamp ) {
	HRESULT r = S_OK;

	LPDIRECT3DTEXTURE9 aTexture = textureManager->getTexture( aStamp->getTextureId() );
	if ( aTexture == NULL ) {
		return E_FAIL;
	}

	if ( aStamp->getPosition() != NULL ) {
		position->x = aStamp->getPosition()->x;
		position->y = aStamp->getPosition()->y;
		position->x -= screenManager->getScreenX();
		position->y -= screenManager->getScreenY();
	} else {
		position->x = 0;
		position->y = 0;
	}

	r = spriteBrush->Draw( aTexture,
		aStamp->getClippingRect(), //CONST RECT *pSrcRect, //NULL uses the whole texture
		aStamp->getCenter(), //CONST D3DXVECTOR3 *pCenter, //NULL uses top left corner as center...
		position, //CONST D3DXVECTOR3 *pPosition, //NULL means no position (0,0,0)
		aStamp->getModulationColor() //D3DCOLOR Color //MODULATION COLOR (TINTING !! - AND TINTING ALPHA !!)
	);

	if ( FAILED( r ) ) {
		GameError( "Could Not Draw sprite" );
		return r;
	}

	spriteBrush->Flush();

	return S_OK;
}

HRESULT SpriteRenderer::renderSpriteToWorld( SpriteStamp* aStamp, RECT* clippingRect ){
	HRESULT r = S_OK;

	LPDIRECT3DTEXTURE9 aTexture = textureManager->getTexture( aStamp->getTextureId() );
	if ( aTexture == NULL ) {
		return E_FAIL;
	}

	if ( aStamp->getPosition() != NULL ) {
		position->x = aStamp->getPosition()->x;
		position->y = aStamp->getPosition()->y;
		position->x -= screenManager->getScreenX();
		position->y -= screenManager->getScreenY();
	} else {
		position->x = 0;
		position->y = 0;
	}

	r = spriteBrush->Draw( aTexture,
		clippingRect, //CONST RECT *pSrcRect, //NULL uses the whole texture
		aStamp->getCenter(), //CONST D3DXVECTOR3 *pCenter, //NULL uses top left corner as center...
		position, //CONST D3DXVECTOR3 *pPosition, //NULL means no position (0,0,0)
		aStamp->getModulationColor() //D3DCOLOR Color //MODULATION COLOR (TINTING !! - AND TINTING ALPHA !!)
	);

	if ( FAILED( r ) ) {
		GameError( "Could Not Draw sprite" );
		return r;
	}

	return S_OK;
}

HRESULT SpriteRenderer::setIdentityMatrix(){
    HRESULT r = S_OK;
    D3DXMatrixIdentity(transform);
    r = spriteBrush->SetTransform(transform);
	if ( FAILED( r ) ) {
		GameError( "Could Not Set Identity" );
		return r;
	}
    return r;
}

HRESULT SpriteRenderer::setScaleMatrix(float scaleX, float scaleY){
    HRESULT r = S_OK; 
    D3DXMatrixScaling(transform, scaleX, scaleY, 1.0);
    r = spriteBrush->SetTransform(transform);
	if ( FAILED( r ) ) {
		GameError( "Could Not Scale Matrix" );
		return r;
	}
    return r;
}

HRESULT SpriteRenderer::beginSprite(){
    HRESULT r = spriteBrush->Begin( D3DXSPRITE_ALPHABLEND );
	if( FAILED( r ) ) {
		GameError( "Could Not Begin Sprite" );
		return r;
	}
    return S_OK;
}

HRESULT SpriteRenderer::endSprite(){
    HRESULT r = spriteBrush->End();
	if( FAILED( r ) ) {
		GameError("Could Not End Sprite");
		return r;
	}
    return S_OK;
}

HRESULT SpriteRenderer::renderTint( int textureId, int red, int green, int blue, int alpha ) {
	position->x = 0;
	position->y = 0;
	HRESULT r = S_OK;

	LPDIRECT3DTEXTURE9 aTexture = textureManager->getTexture( textureId );
	if ( aTexture == NULL ) {
		return E_FAIL;
	}
	r = spriteBrush->Draw( aTexture,
		NULL, //CONST RECT *pSrcRect, //NULL uses the whole texture
		NULL, //CONST D3DXVECTOR3 *pCenter, //NULL uses top left corner as center...
		position, //CONST D3DXVECTOR3 *pPosition, //NULL means no position (0,0,0)
		D3DCOLOR_RGBA(red,green,blue,alpha) //D3DCOLOR Color //MODULATION COLOR (TINTING !! - AND TINTING ALPHA !!)
    );

	if ( FAILED( r ) ) {
		GameError( "Could Not Draw sprite" );
		return r;
	}

	spriteBrush->Flush();
	return S_OK;
}

TextureManager*  SpriteRenderer::getTextureManager(){
    return textureManager;
}
