/*
Copyright (C) 2003-2005 Andrei Nazarov

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

//
// qaa_video.c
//

#include <aalib.h>
#include "qcommon.h"
#include "in_public.h"
#include "vid_public.h"
#include "key_public.h"

aa_context	*qaa_context;

static aa_palette	qaa_palette;

static cvar_t	*qaa_dither;
static cvar_t	*qaa_brightness;
static cvar_t	*qaa_contrast;
static cvar_t	*qaa_gamma;

/*
============
QAA_VideoInit
============
*/
static qboolean QAA_VideoInit( void ) {
	qaa_dither = cvar.Get( "qaa_dither", "0", 0 );
	qaa_brightness = cvar.Get( "qaa_brightness", "80", 0 );
	qaa_contrast = cvar.Get( "qaa_contrast", "63", 0 );
	qaa_gamma = cvar.Get( "qaa_gamma", "1", 0 );
	
	return qtrue;
}

/*
============
QAA_VideoShutdown
============
*/
static void QAA_VideoShutdown( void ) {
	Com_Printf( "Shutting down AALIB video\n" );
	
	if( qaa_context ) {
		Com_Printf( "...destroying AALIB context\n" ); 
		aa_close( qaa_context );
		qaa_context = NULL;
	}
	
}

/*
============
QAA_SetMode
============
*/
/* get the list of acceptable video modes */
#include "vid_modes.h"

static vidSetModeResult_t QAA_SetMode( int *pwidth, int *pheight, byte **buffer,
        int *rowbytes, const byte *palette, int mode, qboolean fullscreen ) {
	int width, height;
	const char *win_fs[] = { "W", "FS" };
	vidSetModeResult_t result = SETMODE_ERROR;
	struct aa_hardware_params hwparams;
	//const struct aa_driver *driver;
	int i;

	Com_Printf( "Initializing display surface\n" );

	Com_Printf( "...setting mode %d: ", mode );

	if( !VID_GetModeInfo( &width, &height, mode ) ) {
		Com_Printf( "invalid mode\n" );
		return SETMODE_ERROR;
	}

	Com_Printf( "%d %d %s\n", width, height, win_fs[fullscreen] );

	*pwidth = width;
	*pheight = height;
	
	//for( driver = aa_drivers; driver; driver++ ) {
	//	Com_Printf( "
	//}
	
	//aa_recommendhidisplay( "x11" );
	
	Com_Printf( "...creating AALIB context: " );
	
	memset( &hwparams, 0, sizeof( hwparams ) );
	hwparams.supported = AA_NORMAL_MASK|AA_BOLDFONT_MASK;//AA_ALL;
	/*hwparams.recwidth = 800;//width; //>> 1;
	hwparams.recheight = 600;//55;//height;// >> 1;
	hwparams.minwidth = 12;
	hwparams.minheight = 9;
	hwparams.maxwidth = 800;
	hwparams.maxheight = 600;*/
	hwparams.font = &aa_fontcourier;
			
	hwparams.width = 1280/8;
	hwparams.height = 800/14;
	if( !( qaa_context = aa_autoinit( &hwparams ) ) ) {
		Com_Printf( "failed\n" );
		return SETMODE_ERROR;
	}
	
	Com_Printf( "ok\n" );
	
	Com_Printf( "...got virtual resolution: %dx%d pixels\n", aa_imgwidth( qaa_context ), aa_imgheight( qaa_context ) );
	Com_Printf( "...got physical resolution: %dx%d characters\n", aa_scrwidth( qaa_context ), aa_scrheight( qaa_context ) );
	
	*pwidth = aa_imgwidth( qaa_context );
	*pheight = aa_imgheight( qaa_context );

	*rowbytes = aa_imgwidth( qaa_context );
	*buffer = aa_image( qaa_context );
	result = SETMODE_WINDOWED;
	
	for( i = 0; i < 256; i++ ) {
		aa_setpalette( qaa_palette, i, palette[0], palette[1], palette[2] );
		palette += 4;
	}

	return result;

}

/*
============
QAA_UpdatePalette
============
*/
static void QAA_UpdatePalette( const byte *palette ) {
	int		i;

	for( i = 0; i < 256; i++ ) {
		aa_setpalette( qaa_palette, i, palette[0], palette[1], palette[2] );
		palette += 4;
	}
}

/*
============
QAA_UpdatePalette
============
*/
static void QAA_UpdateGamma( const byte *table ) {
}

/*
============
QAA_BeginFrame
============
*/
static void QAA_BeginFrame( float stereo_separation ) {
	
}

/*
============
QAA_EndFrame
============
*/
static void QAA_EndFrame( byte **buffer, int *rowbytes ) {
	struct aa_renderparams params;
	
	memset( &params, 0, sizeof( params ) );
	params.dither = qaa_dither->integer;
	params.bright = qaa_brightness->integer;
	params.contrast = qaa_contrast->integer;
	params.gamma = qaa_gamma->value;
	aa_renderpalette( qaa_context, qaa_palette, &params, 0, 0, aa_scrwidth( qaa_context ), aa_scrheight( qaa_context ) );
	aa_flush( qaa_context );
	
}

void Video_PumpEvents( void ) {
	aa_getevent( qaa_context, 0 );
}

static vidFlags_t QAA_GetVideoFlags( void ) {
	return 0;
}


/*
========================================================

MOUSE SUPPORT

========================================================
*/

static qboolean		mouseactive;	// qfalse when not focus app
static qboolean		mouseinitialized;
static int			mouse_x, mouse_y;


/*
===========
QAA_AcquireMouse

Called when the window gains focus or changes in some way
===========
*/
static void QAA_AcquireMouse( void ) {
	int b;
	
	aa_hidemouse( qaa_context );
	aa_getmouse( qaa_context, &mouse_x, &mouse_y, &b );
}


/*
===========
QAA_DeAcquireMouse

Called when the window loses focus
===========
*/
static void QAA_DeAcquireMouse( void ) {
	/* release the mouse */
	aa_showmouse( qaa_context );
}


/*
===========
QAA_SendMouseMoveEvents
===========
*/
static void QAA_SendMouseMoveEvents( void ) {
	int dx, dy;
	int		x, y, b;
	
	if( !qaa_context ) {
		return;
	}
	

	if( !mouseinitialized ) {
		return;
	}

	if( !mouseactive ) {
		return;
	}

	aa_getmouse( qaa_context, &x, &y, &b );
	dx = x - mouse_x;
	dy = y - mouse_y;
	mouse_x = x;
	mouse_y = y;

	if( !dx && !dy ) {
		return;
	}

	com.AddEvent( CE_MOUSEMOVE, dx, dy, NULL );

}

/*
===========
QAA_ShutdownMouse
===========
*/
static void QAA_ShutdownMouse( void ) {
	if( !qaa_context ) {
		return;
	}
	if( !mouseinitialized ) {
		return;
	}
	QAA_DeAcquireMouse();
	mouseactive = qfalse;
	mouseinitialized = qfalse;
}

/*
===========
QAA_InitMouse
===========
*/
static qboolean QAA_InitMouse( void ) {
	if( !qaa_context ) {
		return qfalse;
	}
	if( !aa_autoinitmouse( qaa_context, AA_MOUSEALLMASK ) ) {
		return qtrue;//qfalse;
	}
	mouseinitialized = qtrue;
	return qtrue;
}

/*
===========
QSDL_ActivateMouse

Called when the main window gains or loses focus.
The window may have been destroyed and recreated
between a deactivate and an activate.
===========
*/
static void QAA_ActivateMouse( qboolean active ) {
	if( !qaa_context ) {
		return;
	}
	
	if( !mouseinitialized ) {
		return;
	}

	if( mouseactive == active ) {
		return;
	}

	if( active ) {
		QAA_AcquireMouse();
	} else {
		QAA_DeAcquireMouse();
	}

	mouseactive = active;

}

/*
===================
QAA_ClearMouseStates
===================
*/
static void QAA_ClearMouseStates( void ) {
	/* no work here */
}

/*
============
QAA_Video_FillAPI
============
*/
void Video_FillSWAPI( vidSWAPI_t *api ) {
	api->Init = QAA_VideoInit;
	api->Shutdown = QAA_VideoShutdown;
	api->BeginFrame = QAA_BeginFrame;
	api->EndFrame = QAA_EndFrame;
	api->SetMode = QAA_SetMode;
	api->UpdateGamma = QAA_UpdateGamma;
	api->UpdatePalette = QAA_UpdatePalette;
	api->GetFlags = QAA_GetVideoFlags;
}

void Video_FillGLAPI( vidGLAPI_t *api ) {
    Com_Error(ERR_FATAL,"");
}

/*
===================
Video_FillInputAPI
===================
*/
void Video_FillInputAPI( inputAPI_t *api ) {
	api->Init = QAA_InitMouse;
	api->Shutdown = QAA_ShutdownMouse;
	api->Activate = QAA_ActivateMouse;
	api->Frame = QAA_SendMouseMoveEvents;
	api->ClearStates = QAA_ClearMouseStates;
}

