#include "glfuncs.h"
#include "Screen.h"
#include "Sprite.h"
#include "Parser.h"
#include "AnimatedSprite.h"
#include "ShowOneSprite.h"


using namespace std;

map<string,Sprite *> Sprite::SPRITES;

Sprite* Sprite::instance()
{
	return this;
}

Sprite::Sprite(std::string filename)
:_filename(filename),_direction(LEFT)
{
	_hTexture = glfuncs::instance()->loadTexture(_filename,_coords,_rect);

	_box = _rect;

	// By reversing the [0] and [2] texture mapping coordinates you make the texture face the other direction
	/*
	_coords[0] = 1;
	_coords[1] = 0;
	_coords[2] = 0;
	_coords[3] = 1;
	*/
}

void Sprite::cleanSprites()
{
	for( map<std::string,Sprite *>::iterator i = SPRITES.begin(); i != SPRITES.end(); i++)
		(*i).second->clean();
}

Sprite::Sprite(std::string filename, int width, int height)
:_filename(filename)
{
	_hTexture = glfuncs::instance()->loadTexture(_filename,_coords,_rect);
	_rect.w = width;
	_rect.h = height;
}

Sprite::Sprite(Sprite *sprite)
{
	_filename = sprite->_filename;
	_rect = sprite->_rect;
	_direction = _direction;
	_box = sprite->_box;
}

void Sprite::draw(int x, int y, bool origin)
{
	double tempX;

	if(_direction == RIGHT) {
		double temp = _coords[0];
		_coords[0] = _coords[2];
		_coords[2] = temp;

		tempX = _rect.x;
		_rect.x = _rect.w - (_rect.x+_box.w);
	}
	
	_rect.x = x - _rect.x;
	_rect.y = y - _rect.y;

	if(origin == LEVEL)
		Screen::instance()->drawLevel(_hTexture,_coords,_rect);
	else if(origin == SCREEN)
		Screen::instance()->drawScreen(_hTexture,_coords,_rect);

	_rect.x = x - _rect.x;
	_rect.y = y - _rect.y;
	
	if(_direction == RIGHT) {
		double temp = _coords[0];
		_coords[0] = _coords[2];
		_coords[2] = temp;
		_rect.x = tempX;
	}
}

void Sprite::drawBox(int x, int y, SDL_Rect drawBox)
{
	double temp2 = _coords[2];
	double temp3 = _coords[3];
	int tempWidth = _rect.w;
	int tempHeight = _rect.h;

	_coords[2] *= drawBox.w / ((double)_rect.w);
	_coords[3] *= drawBox.h / ((double)_rect.h);

	_rect.w = drawBox.w;
	_rect.h = drawBox.h;

	draw(x,y);

	_rect.w = tempWidth;
	_rect.h = tempHeight;

	_coords[2] = temp2;
	_coords[3] = temp3;
}

Sprite* Sprite::loadSprite( std::string filename )
{
	if(SPRITES.find(filename) != SPRITES.end()) {
		//cerr << filename << endl;
		return SPRITES[filename]->instance();
	}

	string ext = filename.substr(filename.size() - 3,3);
	if( ext == "png" )
	{
		Sprite *sprite = new Sprite( filename );
		SPRITES[filename] = sprite;
		return sprite;
	}
	else if ( ext == "txt" )
	{
		Sprite *sprite = Sprite::loadText( filename );
		SPRITES[filename] = sprite;
		return sprite;
	}
	
	cerr << "Invalid sprite extension" << endl;
	return NULL;
}

Sprite* Sprite::loadText( std::string filename )
{
	List *spriteInfo = Parser::parse(filename);

	if(spriteInfo->firstString() == "animated") {
		Sprite *newSprite = new AnimatedSprite(filename, spriteInfo->rest());
		delete spriteInfo;
		return newSprite;
	}
	else if(spriteInfo->firstString() == "showone") {
		Sprite *newSprite = new ShowOneSprite(filename, spriteInfo->rest());
		delete spriteInfo;
		return newSprite;
	}
	else {
		cerr << "Sprite type " << spriteInfo->firstString() << " unknown." << endl;
		delete spriteInfo;
		return NULL;
	}
}