/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/drivers/wintel32/video/smpeg/smpeg_video.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/video/video.hpp"
#include "domains/graphics/graphics.hpp"
#include "drivers/wintel32/video/smpeg/smpeg.hpp"


void null_update(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
{
}

tBOOL
CSGXMovieSMPEG::create(const sgxString &filename, const CSGXMovieSMPEG::CMovieParameters &params)
{
	CVideo::create(filename, params);

    SMPEG_Info info;

	m_pMpeg = SMPEG_new(filename.c_str(), &info, FALSE);	// FALSE=play audio

	if ( SMPEG_error(m_pMpeg) ) {
		sgxTrace("%s: %s\n", filename.c_str(), SMPEG_error(m_pMpeg));
		//SMPEG_delete(m_pMpeg);
		return FALSE;
	}

	SMPEG_enableaudio(m_pMpeg, TRUE);
	SMPEG_enablevideo(m_pMpeg, TRUE);
	SMPEG_setvolume(m_pMpeg, (int)(params.fInitialVolume*100.0f));

	/* Enable software bilinear filtering, if desired */
	if (params.bBilearFiltering) {
		SMPEG_Filter *filter;

		filter = SMPEGfilter_bilinear();
		filter = SMPEG_filter(m_pMpeg, filter );
		filter->destroy(filter);
	}

	Uint32 video_flags;
	video_flags = SDL_SWSURFACE;
	video_flags |= SDL_ASYNCBLIT;
	video_flags |= SDL_RESIZABLE;
	// TODO: Resize params, to 256,256?

	if (params.bUseImageData) {
		screen = SDL_CreateRGBSurfaceFrom(params.pImageData->getBitmap(), 
						params.pImageData->getWidth(), params.pImageData->getHeight(),
//						32, params.pImageData->Span(), 0xff0000, 0xffff, 0xff, 0xffff);
						32, params.pImageData->getSpan(), 0xf800, 0x07e0, 0x001f, 0xffff);
	} else {
		screen = SDL_CreateRGBSurface(video_flags, 256, 256, 16, 0xf800, 0x07e0, 0x001f, 0xffff);
	}


	//screen = SDL_SetVideoMode(256, 256, 16, video_flags);
	if ( screen == NULL ) {
	//                fprintf(stderr, "Unable to set %dx%d video mode: %s\n",
	//                              	width, height, SDL_GetError());
		SMPEG_delete(m_pMpeg);
		m_pMpeg = NULL;
		return FALSE;
	}
	SMPEG_setdisplay(m_pMpeg, screen, NULL, null_update);
	SMPEG_scaleXY(m_pMpeg, screen->w, screen->h);
//	m_bValid = TRUE;
	if (params.bLooping) {
		SMPEG_loop(m_pMpeg, 1);
	}
	// TODO
#if 0

		/* seek starting position */
	if(seek) SMPEG_seek(mpeg, seek);

	/* Skip seconds to starting position */
	if(skip) SMPEG_skip(mpeg, skip);
#endif

	return TRUE;
}

CSGXMovieSMPEG::~CSGXMovieSMPEG()
{
	if (m_pMpeg) {
		SMPEG_delete(m_pMpeg);
	}
}

void CSGXMovieSMPEG::pause() 
{
	if (!m_bPaused) {
		SMPEG_pause(m_pMpeg);
	}
	CVideo::pause();
}

void CSGXMovieSMPEG::unpause() 
{
	if (m_bPaused) {
		SMPEG_pause(m_pMpeg);
	}
	CVideo::unpause();
}

void CSGXMovieSMPEG::seek(const tREAL32 time) 
{
	CVideo::seek(time);
	SMPEG_seek(m_pMpeg, (int)time);
}

tBOOL CSGXMovieSMPEG::play() 
{
	SMPEG_play(m_pMpeg);
	return TRUE;
}

tBOOL CSGXMovieSMPEG::isPlaying() 
{
	return SMPEG_status(m_pMpeg) == SMPEG_PLAYING;
}

tBOOL CSGXMovieSMPEG::isPaused() 
{
	return m_bPaused;
}

void CSGXMovieSMPEG::update(const tREAL32 telaps)
{
	if (!m_bPaused) {
		m_fTimecum += telaps;
//		m_pMpeg->update(telaps);
		//seek(m_fTimecum);
	}
}


void  CSGXMovieSMPEG::buildImage(CImageData &data)
{
	// TODO: Params have a 'useImage' flag which writes MPG
	// data into pre-alloc'd bBitmap
	data.create(screen->w, screen->h, CImageData::eRGB);
	// Loop through SDL surface, and extract the data converting
	// to a generic CImageData format
	SDL_LockSurface(screen);

	// TODO: Ignore whole function if own imagedata is supplied
	// BUGWARN: The SGX module for SMPEG assumes 16 bpp
	tUINT16 *pSDLPixels = (tUINT16 *)screen->pixels;
	
	Uint32 &RMask = screen->format->Rmask;
	Uint32 &GMask = screen->format->Gmask;
	Uint32 &BMask = screen->format->Bmask;
	Uint8 &Rshift = screen->format->Rshift;
	Uint8 &Gshift = screen->format->Gshift;
	Uint8 &Bshift = screen->format->Bshift;
	Uint8 &Rloss = screen->format->Rloss;
	Uint8 &Gloss = screen->format->Gloss;
	Uint8 &Bloss = screen->format->Bloss;

	sgxColorRGBA col(sgxColorRGBA::White);
	for(int y=0;y<screen->h;++y) {
		for(int x=0;x<screen->w;++x) {
			col.r = (tREAL32)(((*pSDLPixels & RMask) >> Rshift) << Rloss);
			col.g = (tREAL32)(((*pSDLPixels & GMask) >> Gshift) << Gloss);
			col.b = (tREAL32)(((*pSDLPixels & BMask) >> Bshift) << Bloss);
			// TODO: add this functionality to setPixelAt and/or sgxCOlorRGB
			col.r /= 255.0f;
			col.g /= 255.0f;
			col.b /= 255.0f;
			data.setPixelAt(col, x, y);
			pSDLPixels++;
		}
		pSDLPixels -= screen->w;
		pSDLPixels += screen->pitch/2;
	}
	SDL_UnlockSurface(screen);
}
