#include "GLCanvas.h"

BEGIN_EVENT_TABLE(GLCanvas, wxGLCanvas)
	EVT_PAINT(GLCanvas::OnPaint)
	EVT_MOUSE_EVENTS(GLCanvas::OnMouse)
	EVT_CHAR(GLCanvas::OnKey)
END_EVENT_TABLE()

GLCanvas::GLCanvas(wxWindow *parent)
    : wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxSize(200,200))
{
	Connect(wxID_ANY, wxEVT_PAINT, wxPaintEventHandler(GLCanvas::OnPaint));
	Connect(wxID_ANY, wxEVT_SIZING, wxSizeEventHandler(GLCanvas::OnResize));
}

void GLCanvas::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);

    SetCurrent();

    //glClearColor( 0.3f, 0.4f, 0.6f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // Swap
    SwapBuffers();
}

void GLCanvas::OnMouse(wxMouseEvent& event)
{
	//std::cout << event.GetX() << " " << event.GetY() << std::endl;
}

void GLCanvas::OnResize(wxSizeEvent &event)
{
	std::cout << "size event" << std::endl;
}

void GLCanvas::OnKey(wxKeyEvent &event)
{
}

bool GLCanvas::RenderScene()
{
    wxPaintDC dc(this);
	
    SetCurrent();
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	if(FastRenderingOn || MovePointOn)
	{		
		glEnableClientState(GL_COLOR_ARRAY);
		
		glPointSize(1.0);	
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexArrayID);
		glVertexPointer(3, GL_FLOAT, 0, NULL);
		
		if(UseMonoColor)
			glBindBufferARB(GL_ARRAY_BUFFER_ARB, MonoColorArrayID);
		else
			glBindBufferARB(GL_ARRAY_BUFFER_ARB, ColorArrayID);
		
		glColorPointer(3, GL_UNSIGNED_BYTE, 0, NULL);
		
		glDrawArrays(GL_POINTS, 0, VBOSize);		
	}
	else
	{	
		if(IsSrc)
		{
			glBegin(GL_POINTS);
			
			for(unsigned int i = 0; i < Global.SrcPoints.size(); i++)
			{
				if(UseMonoColor)
					glColor3f(0.0, 1.0, 0.0);
				else		
					glColor3f(Global.SrcPoints[i].r, Global.SrcPoints[i].g, Global.SrcPoints[i].b);
				
				glVertex3f(Global.SrcPoints[i].x, Global.SrcPoints[i].y, Global.SrcPoints[i].z);	
			}
			
			glEnd();						
		}
		else
		{			
			if(MaskSpheres && Spheres.size() == 1)
			{
				float RadiusSq = Spheres[0].radius*Spheres[0].radius;
				
				glBegin(GL_POINTS);

				for(unsigned int i = 0; i < Global.DstPoints.size(); i++)
				{
					Point &P = Global.DstPoints[i];
					
					float dx = P.x - Spheres[0].x;
					float dy = P.y - Spheres[0].y;
					float dz = P.z - Spheres[0].z;
										
					float r, g, b;
					
					if(UseMonoColor)
					{
						r = 0.0;
						g = 1.0;
						b = 0.0;
					}
					else
					{
						r = P.r;
						g = P.g;
						b = P.b;
					}
					
					if(fabs((dx*dx + dy*dy + dz*dz) - RadiusSq) < 2.0)		
					{						
						r = 1.0;
						g = 0.0;
						b = 1.0;
					}
					
					glColor3f(r, g, b);
					glVertex3f(P.x, P.y, P.z);
				}			

				glEnd();				
			}
			else if(MaskSpheres && Spheres.size() == 2)
			{
				float RadiusSq1 = Spheres[0].radius*Spheres[0].radius;
				float RadiusSq2 = Spheres[1].radius*Spheres[1].radius;

				glBegin(GL_POINTS);

				for(unsigned int i = 0; i < Global.DstPoints.size(); i++)
				{
					Point &P = Global.DstPoints[i];
						
					float dx1 = P.x - Spheres[0].x;
					float dy1 = P.y - Spheres[0].y;
					float dz1 = P.z - Spheres[0].z;
					
					float dx2 = P.x - Spheres[1].x;
					float dy2 = P.y - Spheres[1].y;
					float dz2 = P.z - Spheres[1].z;
				
					float DistSq1 = dx1*dx1 + dy1*dy1 + dz1*dz1;
					float DistSq2 = dx2*dx2 + dy2*dy2 + dz2*dz2;

					float r, g, b;
					
					if(UseMonoColor)
					{
						r = 0.0;
						g = 1.0;
						b = 0.0;
					}
					else
					{
						r = P.r;
						g = P.g;
						b = P.b;
					}
					
					if(fabs(DistSq1 - RadiusSq1) < 2.0 && fabs(DistSq2 - RadiusSq2) < 2.0)
					{	
						r = 1.0;
						g = 0.0;
						b = 1.0;						
					}		
					
					glColor3f(r, g, b);
					glVertex3f(P.x, P.y, P.z);
				}		

				glEnd();				
			}
			else
			{
								/*
				glEnableClientState(GL_COLOR_ARRAY);
				
				if(UseMonoColor)
				{
					glDisableClientState(GL_COLOR_ARRAY);
					glColor3f(0.0, 1.0, 0.0);
				}
				

				glColorPointer(3, GL_FLOAT, sizeof(Point), &Global.DstPoints[0].r);	
				glVertexPointer(3, GL_FLOAT, sizeof(Point), &Global.DstPoints[0].x);
				glDrawArrays(GL_POINTS, 0,  Global.DstPoints.size());
				*/
				
				glBegin(GL_POINTS);
				
				for(unsigned int i = 0; i < Global.DstPoints.size(); i++)
				{
					if(UseMonoColor)
						glColor3f(0.0, 1.0, 0.0);
					else
						glColor3f(Global.DstPoints[i].r, Global.DstPoints[i].g, Global.DstPoints[i].b);
						
					glVertex3f(Global.DstPoints[i].x, Global.DstPoints[i].y, Global.DstPoints[i].z);	
				}
				
				glEnd();
			}				
		}
	}		

	for(unsigned int i=0; i < ControlPoints.size(); i++)	
		DrawControlPoints(ControlPoints[i]);	
	
	if(ShowSpheres)
		for(unsigned int i=0; i < Spheres.size(); i++)
			DrawSphere(Spheres[i]);
	
	// Axis
	Point P;
	MyZPR.GetReference(P.x, P.y, P.z);
	DrawAxis(P);
	
	if (gldrawable->is_double_buffered())
		gldrawable->swap_buffers();
	else
		glFlush();
	
	gldrawable->gl_end();	
	
	return true;
}
