/**
 * @class CSDLVideo
 * Classe permettant la gestion d'un ecran SDL.
 * @author Thierry JOUIN
 * @version 1.1
 * @date 08/08/2003
 */

#include "CSDLVideo.h"
#include "CError.h"

/// SDL surface de travail
SDL_Surface *CSDLVideo::_SDLVideo = NULL;
int CSDLVideo::SDLVideoWidth = STANDARD_WIDTH;
int CSDLVideo::SDLVideoHeight = STANDARD_HEIGHT;
void (*CSDLVideo::_userCallbackEventSDL)(SDL_Event *) = NULL;

int CSDLVideo::init(int i_width, int i_height)
{
	// Initialize the SDL library (starts the event loop)
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) 
	{
		return -1;
	}
	// Clean up on exit, exit on window close and interrupt
	atexit(SDL_Quit);
	
	const SDL_VideoInfo* video = SDL_GetVideoInfo();

	if ((_SDLVideo=SDL_SetVideoMode(i_width,i_height, video->vfmt->BitsPerPixel, SDL_HWSURFACE)) == NULL ) 
	{
		return -1;
	}

	SDLVideoWidth = i_width;
	SDLVideoHeight = i_height;

	Uint32 color = SDL_MapRGB(_SDLVideo->format,64,64,64);
	SDL_FillRect(_SDLVideo,NULL,color);

	SDL_EnableKeyRepeat(10,10);

	return 0;
}
void CSDLVideo::finish()
{
	SDL_FreeSurface(_SDLVideo);
	SDL_Quit();
}

void CSDLVideo::setCaption(std::string i_name)
{
	SDL_WM_SetCaption(i_name.c_str(),i_name.c_str());
}

bool CSDLVideo::isFinish()
{
	bool finish = false;
	SDL_Event event;
	Uint8 *keys;

	if ( SDL_PollEvent(&event)==1)
	{
		if (CSDLVideo::_userCallbackEventSDL != NULL)
		{
			CSDLVideo::_userCallbackEventSDL(&event);
		}
		if (event.type == SDL_KEYDOWN)
		{
			keys = SDL_GetKeyState(NULL);
			if (keys[SDLK_ESCAPE] == SDL_PRESSED)
			{
				finish = true;
			}
		}
		if (event.type == SDL_QUIT)
		{
			finish = true;
		}
	}

	return finish;
}

bool CSDLVideo::isSpacePressed()
{
	bool space = false;
	SDL_Event event;
	Uint8 *keys;

	if ( SDL_PollEvent(&event)==1)
	{
		if (CSDLVideo::_userCallbackEventSDL != NULL)
		{
			CSDLVideo::_userCallbackEventSDL(&event);
		}
		if (event.type == SDL_KEYDOWN)
		{
			keys = SDL_GetKeyState(NULL);
			if (keys[SDLK_SPACE] == SDL_PRESSED)
			{
				space = true;
			}
			if (keys[SDLK_ESCAPE] == SDL_PRESSED)
			{
				exit(0);
			}
		}
		if (event.type == SDL_QUIT)
		{
			exit(0);
		}
	}
	return space;
}

bool CSDLVideo::getKeyPressed(SDLKey &key, SDLMod &mod)
{
	SDL_Event event;

	if ( SDL_PollEvent(&event)==1)
	{
		if (CSDLVideo::_userCallbackEventSDL != NULL)
		{
			CSDLVideo::_userCallbackEventSDL(&event);
		}
		if (event.type == SDL_KEYDOWN)
		{
			key = event.key.keysym.sym;
			mod = event.key.keysym.mod;

			if (key == SDLK_ESCAPE)
			{
				exit(0);
			}
			return true;
		}
		if (event.type == SDL_QUIT)
		{
			exit(0);
		}
	}
	return false;
}

bool CSDLVideo::getKeyPressed(SDLKey &key)
{
	SDLMod mod;
	return getKeyPressed(key,mod);
}

void CSDLVideo::waitSpace()
{
	while (!CSDLVideo::isSpacePressed())
	{}
}

void CSDLVideo::setUserCallBackSDL(void (*i_func)(SDL_Event *))
{
	CSDLVideo::_userCallbackEventSDL = i_func;
}

CSDLVideo::CSDLVideo(int i_width,int i_height) :
	Pixels(NULL),
	_SDLSurface(NULL)
{
	ASSERTMSG(_SDLVideo != NULL,"SDL not initialize");

	Width = (i_width < CSDLVideo::SDLVideoWidth) ? i_width : CSDLVideo::SDLVideoWidth;
	Height = (i_height < CSDLVideo::SDLVideoHeight) ? i_height : CSDLVideo::SDLVideoHeight;

	Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	_SDLSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, i_width, i_height, 32, rmask, gmask, bmask, amask);
	ASSERTMSG(_SDLSurface != NULL, SDL_GetError());

	Pixels = (Uint32*)_SDLSurface->pixels;
}

CSDLVideo::CSDLVideo(const CSDLVideo& i_scr) :
	Pixels(NULL),
	Width(i_scr.Width),
	Height(i_scr.Height),
	_SDLSurface(NULL)
{
	ASSERTMSG(_SDLVideo != NULL,"SDL not initialize");

	Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	_SDLSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 32, rmask, gmask, bmask, amask);
	ASSERTMSG(_SDLSurface != NULL, SDL_GetError());

	Pixels = (Uint32*)_SDLSurface->pixels;
	
	lock();
	memcpy(Pixels,i_scr.Pixels,i_scr.Width*i_scr.Height*4);
	unlock();
}

CSDLVideo::~CSDLVideo()
{
	SDL_FreeSurface(_SDLSurface);
}

void CSDLVideo::display()
{
	Uint32 color = SDL_MapRGB(CSDLVideo::_SDLVideo->format,64,64,64);
	SDL_FillRect(_SDLVideo,NULL,color);
	ASSERTMSG( SDL_BlitSurface(_SDLSurface,NULL,CSDLVideo::_SDLVideo,NULL) == 0,"SDL unable to display");
	SDL_UpdateRect(CSDLVideo::_SDLVideo,0,0,0,0);
}

void CSDLVideo::lock()
{
	ASSERTMSG( SDL_LockSurface(_SDLSurface) == 0,"SDL unable to lock surface");
}
void CSDLVideo::unlock()
{
	SDL_UnlockSurface(_SDLSurface);
}

Uint32 CSDLVideo::colorRGB(int i_r, int i_g, int i_b)
{
	return SDL_MapRGB(_SDLSurface->format,i_r,i_g,i_b);
}

void CSDLVideo::fill(int i_x, int i_y, int i_w, int i_h, Uint32 i_color)
{
	SDL_Rect rect;
	rect.x=i_x;
	rect.y=i_y;
	rect.w=i_w;
	rect.h=i_h;
	SDL_FillRect(_SDLSurface,&rect,i_color);
}

void CSDLVideo::resize(int i_width,int i_height)
{
	Width = (i_width < CSDLVideo::SDLVideoWidth) ? i_width : CSDLVideo::SDLVideoWidth;
	Height = (i_height < CSDLVideo::SDLVideoHeight) ? i_height : CSDLVideo::SDLVideoHeight;

	Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	
	SDL_Surface* oldSurface = _SDLSurface;
	Uint32 *oldPixels = (Uint32*)oldSurface->pixels;

	_SDLSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 32, rmask, gmask, bmask, amask);
	ASSERTMSG(_SDLSurface != NULL, SDL_GetError());

	Pixels = (Uint32*)_SDLSurface->pixels;
	
	/*
	lock();
	memcpy(Pixels,oldPixels,Width*Height*4);
	unlock();
	*/
	
	SDL_FreeSurface(oldSurface);
}
