#include <intuition/intuition.h>

#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <graphics/modeid.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>

#include <math.h>
#include <stdlib.h>
#include <string.h>

#include <ModeID.h>

#include "paint.h"

extern void finish_artist( void );

struct Color {
	ULONG pen;
	ULONG red;
	ULONG green;
	ULONG blue;
};

static void finish_graphics( void );

static struct Screen	*scr;
static struct Window	*win;
static struct RastPort	*rp;
static struct Color		*table;
static int				cols;
static int				graph_width;
static int				graph_height;
static UWORD			pens[] = { (UWORD) ~0 };

int quit_xmount	= FALSE;

void plot_pixel( int x, int y, Gun value )
{
	if ( x > 0 ) {
		SetAPen( rp, table[value].pen );
		WritePixel( rp, x, y );
	}
}

void init_graphics(
	int		want_use_root,
	int		*s_graph_width,
	int		*s_graph_height,
	int		ncol,
	Gun		*red,
	Gun		*green,
	Gun		*blue,
	char	*modeid,
	ULONG	depth,
	char	*pubscreen
)
{
	int i;

	table = (struct Color *) malloc( ncol * sizeof( struct Color ) );
	if ( table == NULL ) {
		PutStr( "malloc failed for colour table\n" );
		exit( 1 );
	}

	if ( modeid && depth ) {
		scr = OpenScreenTags(
			NULL,
			SA_Width,		STDSCREENWIDTH,
			SA_Height,		STDSCREENHEIGHT,
			SA_Title,		"AMountains",
			SA_Depth,		depth,
			SA_Type,		CUSTOMSCREEN,
			SA_DisplayID,	ModeID( modeid ),
			SA_Overscan,	OSCAN_STANDARD,
			SA_Pens,		pens,
			SA_SysFont,		1,
			SA_SharePens,	TRUE,
			TAG_DONE
		);
	}

	win = OpenWindowTags(
		NULL,
		WA_Title,				want_use_root ? NULL : "AMountains",
		WA_InnerWidth,			*s_graph_width,
		WA_InnerHeight,			*s_graph_height,
		WA_Backdrop,			want_use_root,
		WA_Borderless,			want_use_root,
		scr ? TAG_IGNORE : WA_PubScreenName,	pubscreen,
		scr ? WA_CustomScreen : TAG_IGNORE,		scr,
		WA_PubScreenFallBack,	TRUE,
		WA_AutoAdjust,			TRUE,
		WA_Flags,				WFLG_NOCAREREFRESH						|
								WFLG_GIMMEZEROZERO						|
								WFLG_ACTIVATE							|
								(want_use_root ? 0 : WFLG_CLOSEGADGET)	|
								WFLG_DEPTHGADGET						|
								WFLG_DRAGBAR,
		WA_IDCMP,				IDCMP_CLOSEWINDOW		|
								IDCMP_ACTIVEWINDOW		|
								IDCMP_INACTIVEWINDOW,
		TAG_DONE
	);
	if ( win == NULL ) {
		PutStr( "Window did not open\n" );
		finish_graphics();
		exit( 1 );
	}

	graph_width  = *s_graph_width  = win->GZZWidth;
	graph_height = *s_graph_height = win->GZZHeight;

	rp = win->RPort;

	for ( i = 0; i < ncol; i++ ) {
		table[i].red	= (red[i]   << 16) | red[i];
		table[i].green	= (green[i] << 16) | green[i];
		table[i].blue	= (blue[i]  << 16) | blue[i];

		table[i].pen = ObtainBestPen(
			win->WScreen->ViewPort.ColorMap,
			table[i].red, table[i].green, table[i].blue,
			OBP_Precision,	PRECISION_EXACT,
			OBP_FailIfBad,	FALSE,
			TAG_DONE
		);

		if ( table[i].pen == -1 ) {
			finish_graphics();
			Printf( "failed to allocate colour %ld\n", i );
			exit( 1 );
		}
		cols++;
	}

	SetBPen( rp, table[SKY].pen );
	SetRast( rp, table[SKY].pen );
}

LONG activepri, inactivepri;

void zap_events( int snooze )
{
	struct IntuiMessage *imsg;

	if ( imsg = (struct IntuiMessage *) GetMsg( win->UserPort ) ) {
		switch ( imsg->Class ) {
			case IDCMP_ACTIVEWINDOW:
				SetTaskPri( FindTask( NULL ), activepri );
				break;
			case IDCMP_INACTIVEWINDOW:
				SetTaskPri( FindTask( NULL ), inactivepri );
				break;
			case IDCMP_CLOSEWINDOW:
				quit_xmount = TRUE;
				break;
		}
		ReplyMsg( (struct Message *) imsg );
	}
	if ( quit_xmount ) {
		finish_graphics();
		finish_artist();
		exit( 0 );
	}
	if ( snooze ) {
		Delay( 50 * snooze );
	}
}

void scroll_screen( int dist )
{
	ScrollRaster( rp, dist, 0, 0, 0, graph_width, graph_height );
}

static void finish_graphics( void )
{
	int i;

	for ( i = 0; i < cols; i++ ) {
		ReleasePen( win->WScreen->ViewPort.ColorMap, table[i].pen );
	}
	if ( win ) CloseWindow( win );
	if ( scr ) CloseScreen( scr );
}
