#include <v_lib.h>
#include <../samples/include/v_show.h>

vec_t v_strtod(char *str)
{
	char dupe[256], *ptr;
	strCopy(dupe,str,256);
	for(ptr=dupe;*ptr;ptr++)
		if(*ptr == ',')
			*ptr = '.';
	return (vec_t)atof(dupe);
}

cam_t					cam;
sdof_control_t			ctl;
sdof_keymap_t			km;
mouse_drag_control_t	mdc;
vhandle_t fnt;
vec3_t min, max;
bstack_t data;

vboolean load_data(char *fname)
{
	u32_t i;
	vec3_t pt={0,0,0}, ext;
	vhandle_t in;
	vec_t *pd;
	in = lexParseFile(fname,NULL);
	if(!in)
		return false;
	/* read in x y pairs */
	bboxClear(min,max);
	stackInit(&data,sizeof(vec3_t));
	while(lexNext(in))
	{
		pt[0] = v_strtod(lexLast(in));
		pt[1] = v_strtod(lexNext(in));
		bboxAddPoint(min,max,pt);
		stackPush(&data,pt);
	}
	lexDestroy(in);
	/* transform data to fit in range [0..1] */
	vec3Sub(ext,max,min);
	ext[0] = 1 / ext[0];
	ext[1] = 1 / ext[1];
	ext[2] = 1;
	vec3Set(ext,0.1,0.1,0.1);
	pd = (vec_t*)stackGetStorage(&data);

	for(i=0;i<stackCount(&data);i++,pd += 3)
	{
		showvec3(pd);
		vec3Sub(pd,pd,min);
		vec3VecScale(pd,pd,ext);
	}
	return true;
}

void V_CALL redraw(void *param)
{
	functional_bounding_box_t fbb;
	
	u32_t count;
	vec3_t pt;
	vec3_t vieworg = {-0.5f,-0.5f,0};
	vec3_t viewext = {1,1,1};

	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	sdcSyncronize(&km,&ctl,&cam);
	camLoadGLTransform(&cam);
	glScalef(10,10,10);
	
	/* Draw XY pairs */
	glPushMatrix();
	
	/*
	glTranslatef(vieworg[0],vieworg[1],vieworg[2]);
	glScalef(viewext[0],viewext[1],viewext[2]);
	*/
	glColor3f(0,0,0);
	/*
	glInterleavedArrays(GL_V3F,0,stackGetStorage(&data));
	glDrawArrays(GL_LINE_STRIP,0,stackCount(&data));
	*/
	glDisableClientState(GL_VERTEX_ARRAY);
	
	glPopMatrix();
	
	/* Draw scales and axes */
	fbbInit(&fbb);
	fbb.cam=&cam;
	vec3Set(fbb.mins,0,0,0);
	vec3Set(fbb.maxs,1,1,1);
	vec3Copy(fbb.f_mins,min);
	vec3Copy(fbb.f_maxs,max);
	
	
	/* fbbDraw2D(&fbb);
	 */
	 
	glColor3f(1,0,0);
	glPointSize(3);
	glBegin(GL_POINTS);
		glVertex3f(0,0,0);
		glVertex3f(5,5,0);
	glEnd(GL_POINTS);
		
	glColor3f(0,0,1);

	vec3Set(pt,0,0,0);
	vglDrawString(pt,cam.origin,"0");
	
	vec3Set(pt,5,5,0);
	vglDrawString(pt,cam.origin,"0");
	
	vglSwapBuffers();
}

int message_loop(void)
{
	vec3_t origin={0,0,0};
	input_record_t in;
	for(;;)
	{
		/* wait for message, limit FPS to 50 */
		if(!vglPending())
			timeDelay(20);
		/* process all messages */
		while(vglPending())
		{
			vglNextEvent(&in);
			if(in.event==ev_key_down)
			{
				switch(in.first_code)
				{
					case key_escape:
						return 0;
					case key_home:
						camLookAt(&cam,origin);
						break;
					case key_scrolllock:
						camSetTarget(&cam,cam.targeted ? NULL : origin);
						break;
					case key_f1:
						vglSaveFramebuffer("out.tga",100,100);
						break;
					case key_f2:
						glLoadIdentity();
						vglDrawToMetafile(libv_clipboard_name,100,100,redraw,NULL);
						break;
					case key_kp_dot:
					{
						/* top - look at xOy */
						vec3_t angles;
						vec3Set(angles,-M_PI2,0,0);
						camDirAndUpFromAngles(&cam,angles);
						vec3Scale(cam.origin,cam.dir,-10);
						break;
					}
				}
			}
			sdckProcessKey(&km,in.event,in.first_code);
			// sdckProcessMouse(&km,&in);
			sdofMouseDragControl(&km,&mdc,&cam,&in);
		}
		/* redraw scene */
		redraw(NULL);
	}
	return 0;
}
	
int main(int argc,char *argv[])
{
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	if(argc < 2)
	{
		conlPuts(LOG_ERROR,"Usage vplot <file with 'x\ty' pairs>\n");
		return -1;
	}
	if(!load_data(argv[1]))
		return -1;
	conlPrintf(LOG_INFO,"Read in %u pairs.\n",stackCount(&data));
	camInit(&cam);
	sdcInit(&ctl);
	sdckInit(&km);
	memZero(&mdc,sizeof(mouse_drag_control_t));
	vglCreateWindow("Plot",0,0,640,480);
	fnt = vglLoadBGIFont("../media/bgi-fonts/arus.chr");
	vglSelectFont(fnt);
	
	glClearColor(1,1,1,1);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-1,1,-1,1,1,100);
	glMatrixMode(GL_MODELVIEW);
	message_loop();
	vglDestroyWindow(vglGetCurrentWindow());
	vglDestroyFont(fnt);
	
	stackClear(&data);
	return 0;
}
