#include ".\groundmanager.h"

GroundManager::GroundManager(void)
{
	spriteRenderer = NULL;
	nonMoveableIter = nonMoveableStamps.begin();
	moveableIter = moveableStamps.begin();
}

GroundManager::~GroundManager(void)
{
	Stamp* aTile;
	for ( StampListIterator iter = nonMoveableStamps.begin();
		  iter != nonMoveableStamps.end();
		  iter++ ) {
		aTile = ( *iter );
		if ( aTile != NULL ) {
			nonMoveableStamps.remove( aTile );
			delete aTile;
			aTile = NULL;
		}
	}
	for ( StampListIterator iter = moveableStamps.begin();
		  iter != moveableStamps.end();
		  iter++ ) {
		aTile = ( *iter );
		if ( aTile != NULL ) {
			moveableStamps.remove( aTile );
			delete aTile;
			aTile = NULL;
		}
	}
}

HRESULT GroundManager::loadGround( char* mapFile ) {
	unloadGround();

	// Load ground overlays
	int mapFileLength = ( int ) strlen( mapFile );
	int groundPathLength = mapFileLength + 7 + 1;
	char* groundPath = ( char* ) malloc( sizeof( char ) * groundPathLength );
	ZeroMemory( groundPath, sizeof( groundPath ) );
	groundPath = strcat( groundPath, mapFile );
	groundPath = strcat( groundPath, ".ground" );

	ifstream groundInput( groundPath );

	int textureId;
	int tileX;
	int tileY;
	int width;
	int height;
	TileStamp* aTile;
	while( groundInput.peek() != -1 ) {
		groundInput >> textureId;
		groundInput >> tileX;
		groundInput >> tileY;
		groundInput >> width;
		groundInput >> height;
		//todo: make less sketchy
		aTile = new TileStamp( textureId, width, height, tileX + 16, tileY + 48 );
		nonMoveableStamps.push_back( aTile );
	}

	if ( groundPath != NULL ) {
		delete groundPath;
		groundPath = NULL;
	}

	nonMoveableStamps.sort( stampCompare );
	nonMoveableIter = nonMoveableStamps.begin();

	return S_OK;
}

void GroundManager::unloadGround() {
	Stamp* aTile;
	for ( StampListIterator iter = nonMoveableStamps.begin();
		  iter != nonMoveableStamps.end();
		  iter++ ) {
		aTile = ( *iter );
		if ( aTile != NULL ) {
			nonMoveableStamps.remove( aTile );
			delete aTile;
			aTile = NULL;
		}
	}
	for ( StampListIterator iter = moveableStamps.begin();
		  iter != moveableStamps.end();
		  iter++ ) {
		aTile = ( *iter );
		if ( aTile != NULL ) {
			moveableStamps.remove( aTile );
			delete aTile;
			aTile = NULL;
		}
	}
}

void GroundManager::init( SpriteRenderer* newSpriteRenderer, ScreenManager* screenManager ) {
	spriteRenderer = newSpriteRenderer;
	stampCompare.setScreen( screenManager );
}

HRESULT GroundManager::renderGround() {
	// Sort it before we draw it
	moveableStamps.sort( stampCompare );
	moveableIter = moveableStamps.begin();
	Stamp* aStamp;

	aStamp = getNextAvailableStamp();
	while( aStamp != NULL ) {
		// TODO:  take away cast and fix
		if ( aStamp->getStampType() == Stamp::SPRITE ) {
			spriteRenderer->renderSpriteToWorld( ( SpriteStamp* ) aStamp );
		} else if ( aStamp->getStampType() == Stamp::TILE ) {
			spriteRenderer->renderTile( ( TileStamp* ) aStamp );
		} else {
			GameError( "RenderGround Encountered unknown object!", aStamp->getTextureId() );
			return E_FAIL;
		}
		aStamp = getNextAvailableStamp();
	}
	moveableIter = moveableStamps.begin();
	nonMoveableIter = nonMoveableStamps.begin();

	return S_OK;
}

HRESULT GroundManager::addMoveableSprite( SpriteStamp* aSprite ) {
	if ( aSprite != NULL ) {
		moveableStamps.push_back( aSprite );
		return S_OK;
	} else {
		return E_FAIL;
	}
}

HRESULT GroundManager::removeMoveableSprite( SpriteStamp* aSprite ){
	StampListIterator iter = moveableStamps.begin();
	while ((iter != moveableStamps.end()) && ((*iter) != aSprite)){
		iter++;
	}
    if((*iter) == aSprite){
        moveableStamps.erase(iter);
	    return S_OK;
    }
    return E_FAIL;
}

Stamp* GroundManager::getNextAvailableStamp() {
	StampListIterator moveEnd = moveableStamps.end();
	StampListIterator nonMoveEnd = nonMoveableStamps.end();

	if ( moveableIter == moveEnd && nonMoveableIter == nonMoveEnd ) {
		return NULL;
	} else if ( moveableIter == moveEnd ) {
		return ( *nonMoveableIter++ );
	} else if ( nonMoveableIter == nonMoveEnd ) {
		return ( *moveableIter++ );
	} else {
		bool moveableAbove = stampCompare.operator () ( ( *moveableIter ), ( *nonMoveableIter ) );
		if ( moveableAbove ) {
			return ( *moveableIter++ );
		} else {
			return ( *nonMoveableIter++ );
		}
	}
}
