//
// batoh@hem2.passagen.se
//
#include "system/xstdio.h"
#include "system/xstddef.h"
#include "system/xstring.h"
#include "formats/v3d.h"
#include "formats/vio.h"
#include "formats/3ds.h"
#include "formats/lws.h"
#include "vmath/vmath.h"
#include "vmath/matrix.h"
#include "render/rnddrv.h"
#include "drivers/drv8.h"
#include "misc/col.h"
//#include "debug/mono.h"
#include "vgui/vgui.h"
#include "vgui/vguicdlg.h"

#define DRIVER vesaDRV

extern DRV DRIVER;
static DRV *drv = &DRIVER;
static BUFF *buff = NULL;

//#define RENDER scpDRV
#define RENDER wfDRV;
#define TOPRND wftopDRV;

extern RNDDRV RENDER;
extern RNDDRV TOPRND;

static RNDDRV *render = &RENDER;
static RNDDRV *rndtop = &TOPRND;

RGB palette[256];

void mymain (int,int,int,int);

VGUIWIN mywin;
V3D *v3d;
static int pause=FALSE, play=FALSE;


static int num_scenes = 0;
V3D *scenes[64];

static float speed=0.5;

#define MBAR_FILE 1000
	#define MBAR_FILE_LV3D 1010
	#define MBAR_FILE_L3DS 1012
	#define MBAR_FILE_LLWS 1014
	#define MBAR_FILE_SV3D 1016
	#define MBAR_FILE_QUIT 1018

#define MBAR_HELP 1100
	#define MBAR_HELP_ABOUT 1101
	#define MBAR_HELP_HELP 1102

#define MBUTT_RESET 1300
#define MBUTT_PAUSE 1301
#define MBUTT_PLAY  1302
#define MBUTT_REWIND 1303
#define MBUTT_FORWARD 1304
#define MBUTT_QUIT 1306
#define MBUTT_LOAD 1307


#define RND_UPDATE 1201
#define MY_VIEW 1200
#define MY_TOP_VIEW 1201
#define MY_FRAME 1202
#define MY_SPEED 1204
#define MY_CAM_SCALE 1205
#define MY_TOP_SCALE 1206
#define MY_ZCLIP_MIN 1207
#define MY_ZCLIP_MAX 1208

#define MY_LBOX 1209

#define MY_DBOX_TEST 1250
#define MY_ABOUT_DIALOG 1251
#define MY_HELP_DIALOG 1252
#define MY_FILE_DIALOG 1253

KEYL mxklist[]={{VG_XALT_F,VGS_COMMAND,VGC_MBAR,MBAR_FILE,0},
								{VG_XALT_S,VGS_COMMAND,VGC_MBAR,2,0},
								{VG_XALT_H,VGS_COMMAND,VGC_MBAR,MBAR_HELP,0}};

char *about_text="Exempel pa ett gui-program...\n\n\nKnappet by Gnilken\n\nFisk 1997!!\n\nGadgets currently supported:\nButtons\nStringbox\nCheckbox\nStatic Text\nBorders\nDrawables\nand\nMenubars.";
char *help_text ="Some commands:\nAlt-H  : Help menu\nAlt-S  : Scene menu\n\nButtons only in it for the fun...\nIf the rendering stops\ntry antoher scene\nor reselect the same\n\nGnilk 1997";
char rnd_info[256];
char speed_info[256];
char scale_info[256];

static void my_render (void)
{
	VGUIGADGET *gad;
	BUFF *old;
	XYZ p;
	int i;

	if ((v3d->framecounter>0) && (!pause) && (play))
	{
		sprintf (rnd_info,"%6.3f",v3d->framecounter);
		vguigad_draw (MY_FRAME);

		old = drv -> activebuff;
		drv->setbuff ( render->buff);

		gad = vguigad_gadfrmhand (MY_VIEW);
		render->setviewport (gad->dab->buff,v3d->activecamera);

		render->prepare (v3d);
		render->render (v3d);
		vguigad_draw (MY_VIEW);

		drv->setbuff (rndtop->buff);

		gad = vguigad_gadfrmhand (MY_TOP_VIEW);
		rndtop->setviewport (gad->dab->buff,v3d->activecamera);
		rndtop->prepare (v3d);
		rndtop->render (v3d);

		vguigad_draw (MY_TOP_VIEW);

		drv->setbuff (old);
	}
	if ((!pause) && (play))
	{
		v3d->framecounter += speed;
		if (v3d->framecounter<0) v3d->framecounter = 0;
	}
	vgui_postmessage (VG_COMMAND,RND_UPDATE,0,0);
}

static void loadv3d (char *filename,int i)
{
  char path[256], *pathptr;

  strcpy( path, filename);
  pathptr = path + strlen( path) - 1;
  while( (pathptr != &path) && (*pathptr != '\\') && (*pathptr != '/'))
    *(pathptr--) = '\0';
  *pathptr = '\0';


  if ((scenes[i] = v3d_load(filename,path,path))==NULL)
	{
		printf ("[!] - %s\n",v3d_geterror ());
		exit (1);
	}
	scenes[i]->framecounter = 0;
	num_scenes++;

}
static void addscene (char *filename,int t)
{
	vguimbar_insertlistitem (mywin.mbar,2,30+num_scenes,filename,0);
	switch (t)
	{
		case 1 : loadv3d (filename,num_scenes); break;
		case 2 : scenes[num_scenes] = load_3ds (filename,0); scenes[num_scenes]->framecounter = 0; num_scenes++; break;
		case 3 : scenes[num_scenes] = lws_load (filename); scenes[num_scenes]->framecounter = 0; num_scenes++; break;

	}
}

void my_dboxinit (void)
{
	vguigad_insert (16,10,64,25,"Quit",VGUIGAD_BUTT,MBUTT_QUIT);
	vguigad_insert (16,30,64,45,"Haba",VGUIGAD_BUTT,MBUTT_FORWARD);
}
void my_dboxmain (int mess, int p1,int p2,int p3)
{
	switch (mess)
	{
		case VG_COMMAND : switch (p1)
											{
												case VGC_BUTTON :
																switch (p2)
																{
																	case MBUTT_QUIT : vgui_postmessage (VGS_EXIT,0,0,0); break;
																}
											}
											break;
		case VG_KEYPRESS :
											if (p1 == 0)
										 	{
												switch (p2)
												{
													case VG_XKEYLEFT :
																break;

													case VG_XKEYRIGHT :
																break;
												}
										 	}
										 break;
		case VG_HELLOW : my_dboxinit ();
										 break;
	}

}
static void my_diagtest (void)
{
	VGUIDBOX *dialog;

	dialog = vguidbox_create (0,0,128,128,"Tjena",MY_DBOX_TEST);
 	dialog -> vgui_main = &my_dboxmain;

	vguidbox_run (MY_DBOX_TEST);
}

static void my_about_init (void)
{
	VGUIGADGET *gad;
	APPLIST *app;
	VGUIDBOX *dbox;
	int xs,ys;

	vguigad_disposelist ();
	app = app_dboxfrmhand (MY_ABOUT_DIALOG);

	dbox = (VGUIDBOX *) app -> win;

	xs = dbox -> x2 - dbox -> x1;
	ys = dbox -> y2 - dbox -> y1;

	gad = vguigad_insert (4,8,xs - 8, ys - 64,"About:",VGUIGAD_TBOX,1);
	gad -> tbox -> text = about_text;
	vguigad_insert (xs/2-32,ys-58,xs/2+32,ys-58+20,"Quit",VGUIGAD_BUTT,MBUTT_QUIT);
}
void my_about_main (int mess, int p1,int p2,int p3)
{
	switch (mess)
	{
		case VG_COMMAND : switch (p1)
											{
												case VGC_BUTTON :
																switch (p2)
																{
																	case MBUTT_QUIT : vgui_postmessage (VGS_EXIT,0,0,0); break;
																}
											}
											break;
		case VG_HELLOW : my_about_init ();
										 break;
	}

}

static void my_about (void)
{
	VGUIGADGET *gad;
	VGUIDBOX *dialog;

	dialog = vguidbox_create (drv->width/4,drv->height/4,drv->width/2+drv->width/4,drv->height/2+drv->height/4,"About",MY_ABOUT_DIALOG);
 	dialog -> vgui_main = &my_about_main;

	vguidbox_run (MY_ABOUT_DIALOG);
}
static void my_help_init (void)
{
	VGUIGADGET *gad;
	APPLIST *app;
	VGUIDBOX *dbox;
	int xs,ys;

	vguigad_disposelist ();
	app = app_dboxfrmhand (MY_HELP_DIALOG);

	dbox = (VGUIDBOX *) app -> win;

	xs = dbox -> x2 - dbox -> x1;
	ys = dbox -> y2 - dbox -> y1;

	gad = vguigad_insert (4,8,xs - 8, ys - 64,"help:",VGUIGAD_TBOX,1);
	gad -> tbox -> text = help_text;
	vguigad_insert (xs/2-32,ys-58,xs/2+32,ys-58+20,"Ok",VGUIGAD_BUTT,MBUTT_QUIT);

}
static void my_help_main (int mess, int p1,int p2,int p3)
{
	switch (mess)
	{
		case VG_COMMAND : switch (p1)
											{
												case VGC_BUTTON :
																switch (p2)
																{
																	case MBUTT_QUIT : vgui_postmessage (VGS_EXIT,0,0,0); break;
																}
											}
											break;
		case VG_HELLOW : my_help_init ();
										 break;
	}
}

static void my_help (void)
{
	VGUIGADGET *gad;
	VGUIDBOX *dialog;

	dialog = vguidbox_create (drv->width/4,drv->height/4,drv->width/2+drv->width/4,drv->height/2+drv->height/4,"Help",MY_HELP_DIALOG);
 	dialog -> vgui_main = &my_help_main;

	vguidbox_run (MY_HELP_DIALOG);

}

void myinit (void)
{
	DRV *drv;
	VGUIGADGET *gad;
	mywin.mbar = vguimbar_create ();
	vguimbar_insertbaritem (mywin.mbar,MBAR_FILE,"File");
	vguimbar_insertbaritem (mywin.mbar,2,"Scene");
	vguimbar_insertbaritem (mywin.mbar,MBAR_HELP,"Help");

	vguimbar_insertlistitem (mywin.mbar,2,30,"Wheels (in the factory)",0);
	vguimbar_insertlistitem (mywin.mbar,2,31,"Gears in action",0);

	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,MBAR_FILE_LV3D,"Load V3D",0);
	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,MBAR_FILE_L3DS,"Load 3DS",0);
	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,MBAR_FILE_LLWS,"Load LWS",0);
	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,0,"",VGUIMBAR_SEPARATOR);
	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,MBAR_FILE_SV3D,"Save V3D",0);
	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,0,"",VGUIMBAR_SEPARATOR);
	vguimbar_insertlistitem (mywin.mbar,MBAR_FILE,VGS_EXIT,"Quit (no save)",0);

	vguimbar_insertlistitem (mywin.mbar,MBAR_HELP,MBAR_HELP_ABOUT,"About SAGA",0);
	vguimbar_insertlistitem (mywin.mbar,MBAR_HELP,MBAR_HELP_HELP,"Help (what is this?)",0);

	vgui_setxkeylist (mxklist,3);

//	addscene ("x:\\scenes\\wheels\\wheels.v3d");
//	addscene ("x:\\scenes\\gears\\coolgear.v3d");


	drv = vgui_getdriver ();
	vguiwin_resize (NULL,drv->width-1,drv->height-1);

//--- first row of controllers...

	gad = vguigad_insert (drv->width/2+16,10,drv->width/2+16+120,30,"Frame:",VGUIGAD_TBOX,MY_FRAME);
	sprintf (rnd_info,"%6.3f",v3d->framecounter);
	gad -> tbox -> text = rnd_info;
	gad = vguigad_insert (drv->width/2+16,35,drv->width/2+16+120,55,"Speed:",VGUIGAD_TBOX,MY_SPEED);
	sprintf (speed_info,"%6.3f",speed);
	gad -> tbox -> text = speed_info;
	vguigad_insert (drv->width/2+16,60,drv->width/2+16+120,75,"Play",VGUIGAD_BUTT,MBUTT_PLAY);
	vguigad_insert (drv->width/2+16,80,drv->width/2+16+120,95,"Pause",VGUIGAD_BUTT,MBUTT_PAUSE);
	vguigad_insert (drv->width/2+16,100,drv->width/2+16+120,115,"Rewind",VGUIGAD_BUTT,MBUTT_REWIND);
	vguigad_insert (drv->width/2+16,120,drv->width/2+16+120,135,"Forward",VGUIGAD_BUTT,MBUTT_FORWARD);
	vguigad_insert (drv->width/2+16,140,drv->width/2+16+120,155,"Reset",VGUIGAD_BUTT,MBUTT_RESET);
	gad = vguigad_insert (drv->width/2+16,160,drv->width/2+16+120,180,"Cam-Scale:",VGUIGAD_SBOX,MY_CAM_SCALE);
	sprintf (gad->sbox->string,"%6.3f",(float)1.0);
	gad = vguigad_insert (drv->width/2+16,185,drv->width/2+16+120,205,"Top-Scale:",VGUIGAD_SBOX,MY_TOP_SCALE);
	sprintf (gad->sbox->string,"%6.3f",(float)1.0);

//--- second row of controllers...

	gad = vguigad_insert (drv->width/2+144,10,drv->width/2+155+120,30,"Zclip (min):",VGUIGAD_SBOX,MY_ZCLIP_MIN);
	sprintf (gad->sbox->string,"%f",scenes[0]->zmin);
	gad = vguigad_insert (drv->width/2+144,35,drv->width/2+155+120,55,"Zclip (max):",VGUIGAD_SBOX,MY_ZCLIP_MAX);
	sprintf (gad->sbox->string,"%f",scenes[0]->zmax);


	gad = vguigad_insert (drv->width/2+144,60,drv->width/2+155+120,200,"Testlist:",VGUIGAD_LBOX,MY_LBOX);
	vguilbox_additem (MY_LBOX,"a - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"b - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"c - Kalle Anka");
	vguilbox_additem (MY_LBOX,"d - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"e - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"f - Kalle Anka");
	vguilbox_additem (MY_LBOX,"g - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"h - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"i - Kalle Anka");
	vguilbox_additem (MY_LBOX,"j - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"k - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"l - Kalle Anka");
	vguilbox_additem (MY_LBOX,"m - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"n - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"o - Kalle Anka");
	vguilbox_additem (MY_LBOX,"p - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"q - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"r - Kalle Anka");


	vguigad_insert (4,10,drv->width/2-4,drv->height/2-20,"Camera View",VGUIGAD_BORD,1);
	vguigad_insert (4,drv->height/2-10,drv->width/2-4,drv->height-4,"Top View",VGUIGAD_BORD,2);

	gad = vguigad_insert (8,20,drv->width/2-8,drv->height/2-24,"",VGUIGAD_DAB,MY_VIEW);
	render->setviewport (gad->dab->buff,v3d->activecamera);

	if (drv->width<640)	render->scale = 0.5;
		else render->scale = 1.0;

	gad = vguigad_insert (8,drv->height/2,drv->width/2-8,drv->height-24,"",VGUIGAD_DAB,MY_TOP_VIEW);
	rndtop->setviewport (gad->dab->buff,v3d->activecamera);
	rndtop->scale = 1.0;


	//if (drv->width<640)	render->scale = 0.5;
//		else render->scale = 1.0;

	my_render ();
}
static void testlbox (void)
{
	vguilbox_clear (MY_LBOX);
	vguilbox_additem (MY_LBOX,"1 - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"2 - Gnilk of Noice");
	vguilbox_additem (MY_LBOX,"3 - Kalle Anka");
	vguilbox_additem (MY_LBOX,"4 - Fredrik Kling");
	vguilbox_additem (MY_LBOX,"5 - Gnilk of Noice");
	vguigad_draw (MY_LBOX);
}

static char filename[256];

void mymain (int mess, int p1,int p2,int p3)
{
	VGUIGADGET *gad;

	switch (mess)
	{
		case VG_COMMAND : switch (p1)
											{
												case VGC_SBOX :
																switch (p2)
																{
																	case MY_TOP_SCALE :
																				gad = vguigad_gadfrmhand (MY_TOP_SCALE);
																				rndtop->scale = atof (gad->sbox->string);
																				break;
																	case MY_CAM_SCALE :
																				gad = vguigad_gadfrmhand (MY_CAM_SCALE);
																				render->scale = atof (gad->sbox->string);
																				break;
																	case MY_ZCLIP_MIN :
																				gad = vguigad_gadfrmhand (MY_ZCLIP_MIN);
																				v3d->zmin = atof (gad->sbox->string);
																				break;
																	case MY_ZCLIP_MAX :
																				gad = vguigad_gadfrmhand (MY_ZCLIP_MAX);
																				v3d->zmax = atof (gad->sbox->string);
																				break;
																}
																break;
												case VGC_MBAR :
																//vguiwin_clearUA();
																switch (p2)
																{
																	case MBAR_FILE_LV3D : if (vguicdlg_file (FILEFLAG_LOAD,filename))
																												{
																													addscene (filename,1);
																												}
																												break;
																	case MBAR_FILE_L3DS : if (vguicdlg_file (FILEFLAG_LOAD,filename)) addscene (filename,2); break;
																	case MBAR_FILE_LLWS : if (vguicdlg_file (FILEFLAG_LOAD,filename)) addscene (filename,3); break;


																	//case MBAR_DRIVER_RND : rnd_driver (); break;//vguiwin_printfxy (0,10,"File-close"); break;
																	//case MBAR_DRIVER_PRC : prc_driver (); break;
																	case 30 :
																	case 31 :
																	case 32 :
																	case 33 :
																	case 34 : v3d = scenes[p2-30]; v3d->framecounter = 0; my_render(); break;
																	case MBAR_HELP_ABOUT : my_about (); break;
																	case MBAR_HELP_HELP : my_help (); break;
																	case VGS_EXIT : vgui_postmessage (VGS_EXIT,0,0,0); break;
																}
																break;
												case VGC_BUTTON :
																switch (p2)
																{
																	case MBUTT_RESET : v3d->framecounter = 0; break;
																	case MBUTT_PLAY : play = TRUE;
																										if (pause) pause = FALSE;
																										break;
																	case MBUTT_PAUSE : if (pause) pause = FALSE;
																										 else pause = TRUE;
																										 break;
																	case MBUTT_REWIND : if (speed>0) speed = speed * -1;
																											sprintf (speed_info,"%6.3f",speed);
																											vguigad_draw (MY_SPEED);
																											break;
																	case MBUTT_FORWARD : /*if (speed<0) speed = speed * -1;
																											 sprintf (speed_info,"%6.3f",speed);
																											 vguigad_draw (MY_SPEED);
																											 */
																											 testlbox ();
																											 break;

																}
																break;

												case RND_UPDATE :
															my_render ();
															break;
											}
											break;
		case VG_KEYPRESS :
											if (p1 == 0)
										 	{
												switch (p2)
												{
													case VG_XKEYLEFT :
																speed-=0.1;
																sprintf (speed_info,"%6.3f",speed);
																vguigad_draw (MY_SPEED);
																break;

													case VG_XKEYRIGHT :
																speed+=0.1;
																sprintf (speed_info,"%6.3f",speed);
																vguigad_draw (MY_SPEED);
																break;
												}
										 	}
										 break;
		case VG_HELLOW : myinit ();
										 break;
	}
}
void close (void)
{
	drv->exit ();
	mathclose ();
}

void init (void)
{
  int i;


	mathinit ();
	if (!drv->setup ())
	{
    printf ("[!] Error: Driver setup failed!\n");
		exit (1);
	} else {
           printf("þ Available modes:\n");
					 for( i=0; i<drv->modes; i++)
             printf("  - %dx%d\n", drv->modelist[i].width, drv->modelist[i].height);
				 }

  //if(!drv->init(drv->modelist[0].width, drv->modelist[0].height, 0))
  if(!drv->init(640,480, 0))
	{
    printf("[!] Error: Unable to initilize %s.(%s)\n", drv->name, drv->geterror());
		exit(0);
	}
/*
  if (!drv->mouseinit( 0, 0, drv->width - 1, drv->height - 1))
	{
		drv->exit();
    printf("[!] Error: Unable to initilize mousedriver.\n");
		exit(0);
	}
*/
  buff = drv->createbuff( drv->width, drv->height);
	drv->setbuff( buff);

	for (i=0;i<255;i++)
	{
		palette[i].r = 255;
		palette[i].g = 255;
		palette[i].b = 255;
	}
  drv->setpalette( palette);
}


void main (void)
{
	num_scenes = 0;

  loadv3d ("scenes\\wheels\\wheels.v3d",0);
  loadv3d ("scenes\\gears\\coolgear.v3d",1);

	v3d = scenes[1];
	v3d->framecounter = 0;

	init ();

	// Preset some default values...

	vguiwin_setup (&mywin);

	mywin.handle = 1;
	mywin.caption = (char *)xmalloc (sizeof (char) * 256);
	sprintf (mywin.caption,"V3D Fuckup program, Gnilk 1997.");
	mywin.vgui_main = &mymain;


	vgui_init (drv,FALSE);
	vgui_register (&mywin);
	vguiwin_update (NULL);
	vgui_main ();

	mathclose ();
	close ();
}


