#include "SurfaceManager.h"
#include "dinput.h"
#include "ScreenManager.h"


//Default constructor
SurfaceManager::SurfaceManager() {

}

//Set the D3D Device
void SurfaceManager::setDirect3DDevice( LPDIRECT3DDEVICE9 newd3dDevice ) {
	m_pd3dDevice = newd3dDevice;
}

//Deconstructor
SurfaceManager::~SurfaceManager(void) {

}

//Returns a pointer to a surface
Surface* SurfaceManager::getSurface( char* surfaceName ) {
	return surfaces[ surfaceName ];
}

// Adds a surface to the list when given the filename of the source
HRESULT SurfaceManager::addSurface( char* fileName ) {
	Surface* surface = loadSurfaceFromFile( fileName );
	if ( surface == NULL ) {
		return E_FAIL;
	}
    //Adds to the list since there's no problems with the fileName
	surfaces[ fileName ] = surface;

	return S_OK;
}


//Adds a surface to the list when given
//the filename of the source and where it should appear on the screen
HRESULT SurfaceManager::addSurface( char* fileName, int x, int y ) {
	HRESULT r = addSurface( fileName );
	if ( FAILED( r ) ) {
		return E_FAIL;
	}

	Surface* surface = getSurface( fileName );
	if ( surface == NULL ) {
		return E_FAIL;
	}

    surface->setX( x );
	surface->setY( y );

	return S_OK;
}


//Loads a surface from a fileName passed as a parameter
Surface* SurfaceManager::loadSurfaceFromFile( char* fileName ) {
    HRESULT r = E_FAIL;
	LPDIRECT3DSURFACE9 m_pSurface = NULL;

	//get information about image
	D3DXIMAGE_INFO imgInfo;
	r = D3DXGetImageInfoFromFile( fileName, 
		&imgInfo);
	if( FAILED( r ) ) {
		GameError( "Could Not Get Info About Test Image" );
		return NULL;
	}
	
	//create surface for image
	r = m_pd3dDevice->CreateOffscreenPlainSurface( 
		imgInfo.Width, imgInfo.Height, imgInfo.Format, D3DPOOL_SCRATCH, 
		&m_pSurface, NULL );
	if(FAILED(r)) {
		GameError("Could not create surface for image");
		return NULL;
	}
	
	//load the image into the surface
	r = D3DXLoadSurfaceFromFile(
			m_pSurface,     //dest surface
			NULL,             //palette entry
			NULL,             //destination rect (null = all)
			fileName,         //file name string
			NULL,             //source rect
			D3DX_FILTER_NONE, //filter to use
			0,                //color key to use
			&imgInfo          //info object
		);

	if(FAILED(r)) {
		GameError("Could not load image into surface");
		return NULL;
	}

	return new Surface( fileName, imgInfo.Width, imgInfo.Height, m_pSurface );
}


//Renders the surfaces
HRESULT SurfaceManager::renderSurface( char* imageName, LPDIRECT3DSURFACE9 toRenderTo ) {
	Surface* surface = getSurface( imageName );
	if ( surface == NULL ) {
		GameError( "Could not load suface: " );
		GameError( imageName );
		return E_FAIL;
	}

	int x = surface->getX();
	int y = surface->getY();
	int height = surface->getHeight();
	int width = surface->getWidth();

	//images not mapped onto triangles are
	//considered SURFACES - or areas in memory
	HRESULT r;

	//POINT DestPoint = { 100, 100 };
	RECT DestRect = {0, 0, width, height };
	RECT DestRectX = {x, y, width + x, height + y };

	/*
	//THIS WILL CURRENTLY FAIL IN WINDOWED MODE
	//copy image surface into back buffer surface
	r = m_pd3dDevice->CopyRects(
		m_pImageSurf, //source surface
		&DestRect,    //rect or array of rects from source
		1,            //int num of rects to copy
		m_pBackSurf,    //target surface
		&DestPoint    //point or array of points as offsets
	);
	*/
	
	//almost the same as above, BUT it converts between
	//different formats and sizes automagically
	r = D3DXLoadSurfaceFromSurface(
			toRenderTo,  //targetSurface
			NULL,  //destination pallette index
			&DestRectX, //destination rect
			surface->getSurface(), //source surface
			NULL,  //source pallette index
			&DestRect, //source rect, anything outside clipped
			D3DX_FILTER_NONE, //filter to use when copying
			0 //color_key  (zero disables color key)
		);
    

	if(FAILED(r)) {
		GameError("Failed on image draw for");
		GameError( imageName );
		return r;
	}
	
	return S_OK;
}

//Allows us to move a surface around the window
HRESULT SurfaceManager::moveSurface( char* surfaceName, int key ) {
	Surface* surface = getSurface( surfaceName );
	if ( surface == NULL ) {
		return E_FAIL;
	}

	//moves the surface 5 pixels in a direction and bounds checks
	//to make sure that it doesn't go outside the viewable window area
	if ( key == DIK_UP ) {
		int newY = surface->getY() - 5;
		if ( newY >= 0 ) {
			surface->setY( newY );
		}
	} else if ( key == DIK_DOWN ) {
		int newY = surface->getY() + 5;
		if ( newY + surface->getHeight() <= ScreenManager::getWindowHeight() ) {
			surface->setY( newY );
		}
	} else if ( key == DIK_RIGHT ) {
		int newX = surface->getX() + 5;
		if ( newX + surface->getWidth() <= ScreenManager::getWindowWidth() ) {
			surface->setX( newX );
		}
	} else if ( key == DIK_LEFT ) {
		int newX = surface->getX() - 5;
		if ( newX >= 0 ) {
			surface->setX( newX );
		}
	}

	return S_OK;
}
