#ifndef _TMAGAME_CPP_
#define _TMAGAME_CPP_

#include "ma_allegro.h"

// **************************************
// Definición de métodos de clase TMAGame
// **************************************
//
REGISTER_CLASS_ID(TMAGame);

PMAGame TMAGame::oc_MAGame=NULL;
bool TMAGame::ci_endgame=false;
bool TMAGame::ib_soundAvailable=false;
long TMAGame::il_time_millis=0;

TMAGame::TMAGame(void)
{
    if (oc_MAGame!=NULL)
    {
        showAlert("Solo puede haber una instancia de la clase TMAGame");
        exit(0);
    }
    oc_MAGame = this;
    ia_screen_buffer[0]=NULL;
    ia_screen_buffer[1]=NULL;
    io_current_scene=NULL;
    io_next_scene=NULL;
    ib_remove_last_scene=false;
    setGameFPS(0);    
}

TMAGame::~TMAGame()
{
    cleanup();
}

void TMAGame::setGameFPS(int fps)
{
    ii_game_speed = (fps<=0)?0:(1000/fps);
}

int TMAGame::getRGBColor(int red,int green,int blue)
{
    return makecol(red,green,blue);
}

PMAGame TMAGame::getCurrentGame(void)
{
    return oc_MAGame;
}


/*
long TMAGame::getCPUTime(void)
{
    return (long)(clock()/(CLOCKS_PER_SEC/1000));
}
*/

long TMAGame::getCPUTime(void)
{
    return TMAGame::il_time_millis;
}

void TMAGame::sleep(int ms)
{
    rest(ms);
}

void TMAGame::showAlert(const char *txt)
{
    allegro_message(txt);
}

void TMAGame::showLastAlert()
{
    allegro_message(allegro_error);
}

void TMAGame::showFatalError(const char *txt)
{
    showAlert(txt);
    endGame();
}

void TMAGame::setWindowTitle(const char *txt)
{
//    set_window_title(txt);
}

void TMAGame::getScreenSize(int& width,int& height)
{
    width = screen->w;
    height = screen->h;
}

int TMAGame::getScreenWidth(void)
{
    return screen->w;
}

int TMAGame::getScreenHeight(void)
{
    return screen->h;
}

bool TMAGame::make_screen_buffer(int width,int height,int depth)
{    
    // Creamos la pantalla para doble buffer
	//
	if (ia_screen_buffer[1])
    {
        delete ia_screen_buffer[1];
        ia_screen_buffer[1]=NULL;
    }
    
    // Intentamos crear el backbuffer
    //
    ia_screen_buffer[1] = TMABitmap::create(width,height,depth);
    
    // No se ha podido inicializar el buffer en memoria
    //
    if (!ia_screen_buffer[1]) return false;
    
    // Ahora la pantalla principal
    //
    if (ia_screen_buffer[0]) 
	{
        delete ia_screen_buffer[0];
        ia_screen_buffer[0] = NULL;
    }
    
    // Directamente el buffer principal es la memoria video.
    //
    ia_screen_buffer[0] = new TMABitmap(screen,true);
        
    return true;
}

void TMAGame::flip_screen_buffer(void)
{
    acquire_screen();
    stretch_blit(
        ia_screen_buffer[1]->getInternalBitmapRef(),
        ia_screen_buffer[0]->getInternalBitmapRef(),
        0,0,640,480,
        0,0,320,240);
    release_screen();
}   
    
bool TMAGame::setGraphicsMode(int width,int height,int colordepth,bool fullscreen)
{
    int ax,ay,ret;
    
      
    // Establecemos la densidad de colores.
    //  
    set_color_depth(16);
   	    	
	if (!fullscreen)
	{
        ret = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0);
    }
    else
    {
        ret = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0);
    }       
		
    ret = ( (ret==0) && make_screen_buffer(width,height,16));
    
    // Esperamos un segundo, para que se establezca correctamente el modo grafico.
    //
	textprintf_centre_ex(screen,font,160,100,makecol(200,200,200),-1,"Loading...");
    sleep(1000);
    
    return ret;
}


PMABitmap TMAGame::getScreenBuffer(void) { return ia_screen_buffer[1]; }
PMABitmap TMAGame::getScreen(void) { return ia_screen_buffer[0]; }

int TMAGame::getScreenBufferDepth(void)  { return bitmap_color_depth(ia_screen_buffer[1]->getInternalBitmapRef()); }
        
void TMAGame::cleanup(void)
{    
	if (ia_screen_buffer[0] != NULL) 
    {
        delete ia_screen_buffer[0];
        ia_screen_buffer[0] = NULL;
    }

	if (ia_screen_buffer[1] != NULL) 
	{
        delete ia_screen_buffer[1];
        ia_screen_buffer[1] = NULL;
    }
}

void TMAGame::endGame(void)
{
    ci_endgame = true;
}

void TMAGame::run(void)
{    
unsigned char i;
    long startTime=0,cur_wait ;
    
    // Inicialización de Entorno
    //
	install_joystick(JOY_TYPE_AUTODETECT);
	for (i=0;i<joy[0].num_buttons;i++) joy[0].button[i].b=0;
	set_display_switch_mode(SWITCH_BACKGROUND);

    // ---- CICLO PRINCIPAL DEL JUEGO
    //
    while (!ci_endgame)
    {
        if (ii_game_speed) startTime = getCPUTime() + ii_game_speed;
        
        // Invocamos el RUN
        //
        if ( (io_current_scene==NULL) || (!io_current_scene->doRun()) ) doRun();
        
        if (io_next_scene==NULL)
        {
            // Invocamos el Paint
            //
            if (!io_current_scene) doPaint(*ia_screen_buffer[1]);
            else io_current_scene->doPaint(*ia_screen_buffer[1]);
            flip_screen_buffer();
        }
        else
        {
            // Establecemos la nueva escena, si se cambio.
            //
            if (ib_remove_last_scene && io_current_scene!=NULL) delete io_current_scene;
            io_current_scene = io_next_scene;
            io_next_scene=NULL;
        }
        
        // Duerme el tiempo necesario.
        //
        if (ii_game_speed>0)
        {
            cur_wait = startTime - getCPUTime();
            if (cur_wait>0) sleep(cur_wait);
        }
    }
    //
    // ----------- FIN DE CICLO PRINCIPAL
    
    // Finalización
    //
}

bool TMAGame::setScene(PMAScene esc,const PMAObject params,bool remove_last)
{
    if (io_next_scene!=NULL)
    {
        delete io_next_scene;
        io_next_scene=NULL;
    }
    
    if (!esc->isInitialized())
    {
        if (!esc->doInit(params)) return false;
        io_next_scene = esc;
        ib_remove_last_scene=remove_last;
    }
    
    return true;
}

// ***************************************
// Definición de métodos de clase TMAScene
// ***************************************
//
REGISTER_CLASS_ID(TMAScene);

TMAScene::TMAScene()
{
    ib_initialized=false;
    ii_Estado=0;
}

bool TMAScene::doInit(const PMAObject params)
{
    ib_initialized=true;
    return true;
}

#endif
