#include <v_lib.h>

void V_GLOBAL
vglFlushEvents(void)
{
	/* TODO: move to core */
	input_record_t ev;
	while(vglPending())
		vglNextEvent(&ev);
}

u32_t V_GLOBAL
vglGetKey()
{
	/*
	 * TODO:
	 * vboolean vglPeekEvent(int type,input_record_t *ev_ret,vboolean remove);
	 */
	input_record_t ev;
	while(vglNextEvent(&ev))
		if(ev.event == ev_key_up)
			return ev.first_code;
	return 0xffffffff;
}

void line2v(vec2_t origin,vec2_t dir)
{
	vec2_t p1, p2;
	vec2Scale(p1,dir,-200);
	vec2Add(p1,p1,origin);
	vec2Scale(p2,dir,200);
	vec2Add(p2,p2,origin);
	glBegin(GL_LINES);
		glVertex2d(p1[0],p1[1]);
		glVertex2d(p2[0],p2[1]);
	glEnd();
}

void line2(vec_t origin_x,vec_t origin_y,
	vec_t dir_x,vec_t dir_y)
{
	vec2_t o, d;
	vec2Set(o,origin_x,origin_y);
	vec2Set(d,dir_x,dir_y);
	line2v(o,d);
}


void draw_triangle(vec3_t a,vec3_t b,vec3_t c)
{
	glBegin(GL_LINE_LOOP);
		VGL_VERTEX3V(a);
		VGL_VERTEX3V(b);
		VGL_VERTEX3V(c);
	glEnd();
}

void draw_tri(matrix3_t m)
{
	vec3_t a = {50,10,1}, b = {70,10,1}, c = {60,40,1};
	vec3_t at, bt, ct;
	mat3VecMul(at,m,a);
	mat3VecMul(bt,m,b);
	mat3VecMul(ct,m,c);
	draw_triangle(at,bt,ct);
}

void compute_base(vec2_t dest,vec2_t origin,vec2_t dir)
{
	vec_t nr0 = - dir[1] * origin[0] + dir[0] * origin[1];
	vec_t dir2 = dir[0] * dir[0] + dir[1] * dir[1];
	nr0 /= dir2;
	dest[0] = -dir[1] * nr0;
	dest[1] = dir[0] * nr0;
}

void line2_mirror(matrix3_t dest,vec2_t origin,vec2_t dir)
{
	vec2_t base;
	vec_t cosa = dir[1];
	vec_t sina = dir[0];
	matrix3_t temp, t, rz, mirrory;

	compute_base(base,origin,dir);
	mat3Unit(t);
	t[0][2] = base[0];
	t[1][2] = base[1];

	mat3Unit(rz);
	rz[0][0] = cosa;
	rz[1][1] = cosa;
	rz[0][1] = sina;
	rz[1][0] = -sina;

	mat3MatMul(temp,t,rz);

	mat3Unit(mirrory);
	mirrory[0][0] = -1;
	mat3MatMul(dest,temp,mirrory);

	rz[0][1] = -sina;
	rz[1][0] = sina;
	mat3MatMul(temp,dest,rz);

	t[0][2] = -base[0];
	t[1][2] = -base[1];
	mat3MatMul(dest,temp,t);
}

void draw_scene(vec2_t origin,vec2_t dir)
{
	matrix3_t t;
	vec2Unit(dir,dir);
	glLoadIdentity();
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1,1,1);
	line2(0,0,1,0);
	line2(0,0,0,1);
	mat3Unit(t);
	draw_tri(t);
	line2_mirror(t,origin,dir);
	glColor3f(1,1,0);
	draw_tri(t);
	glColor3f(1,0,1);
	line2v(origin,dir);
	vglSwapBuffers();
	vglFlushEvents();
	vglGetKey();
}

int main()
{
	int i;
	vec_t arg = 0;
	vglCreateWindow("Planar mirror transform",0,0,512,512);
	glMatrixMode(GL_PROJECTION);
	glOrtho(-100,100,-100,100,-100,100);
	glMatrixMode(GL_MODELVIEW);
	for(i=0;i<20;i++,arg += 0.1)
	{
		vec2_t origin = {0,0};
		vec_t s = sin(arg), c = cos(arg);
		vec2_t dir = {1,0}, dir2;
		matrix2_t rz;
		rz[0][0] = rz[1][1] = c;
		rz[0][1] = -s;
		rz[1][0] = s;
		mat2VecMul(dir2,rz,dir);
		/* origin[0] = arg * 20; */
		draw_scene(origin,dir2);
	}
	while(vglGetKey() != key_escape);
	vglDestroyWindow(vglGetCurrentWindow());
	return 0;
}
