#include "global.h"
#include "Piece.h"
#include <stdio.h>

//#include "OBJParser.h"
#include "TextureLoader.h"

#include <iostream>
#include <fstream>
#include <math.h>
#include <time.h>
#include <vector>

CPiece* g_grid[k_numRows][k_numCols];
CPiece* g_firstPiece;
GLuint g_fighterList;
GLuint g_knightList;
GLuint g_propellerList;
GLuint g_pickList;
GLuint g_carList;
GLuint g_killnerList;
TextureLoader *g_pTextureLoader = new TextureLoader();
glTexture g_fighterTexture;
glTexture g_knightTexture;
glTexture g_propellerTexture;
glTexture g_pickTexture;
glTexture g_carTexture;
glTexture g_killnerTexture;

using namespace std;

vector<CPiece *> findMatches();

/* obj loader starts here */
/*
* obj.c -- obj model loader
* last modification: aug. 14, 2007
*
* Copyright (c) 2005-2007 David HENRY
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* gcc -Wall -ansi -lGL -lGLU -lglut obj.c -o obj
*/



/* Vectors */
typedef float vec3_t[3];
typedef float vec4_t[4];

/* Vertex */
struct obj_vertex_t
{
	vec4_t xyzw;
};

/* Texture coordinates */
struct obj_texCoord_t
{
	vec3_t uvw;
};

/* Normal vector */
struct obj_normal_t
{
	vec3_t ijk;
};

/* Polygon */
struct obj_face_t
{
	GLenum type;        /* primitive type */
	int num_elems;      /* number of vertices */

	int *vert_indices;  /* vertex indices */
	int *uvw_indices;   /* texture coordinate indices */
	int *norm_indices;  /* normal vector indices */
};

/* OBJ model structure */
struct obj_model_t
{
	int num_verts;                     /* number of vertices */
	int num_texCoords;                 /* number of texture coords. */
	int num_normals;                   /* number of normal vectors */
	int num_faces;                     /* number of polygons */

	int has_texCoords;                 /* has texture coordinates? */
	int has_normals;                   /* has normal vectors? */

	struct obj_vertex_t *vertices;     /* vertex list */
	struct obj_texCoord_t *texCoords;  /* tex. coord. list */
	struct obj_normal_t *normals;      /* normal vector list */
	struct obj_face_t *faces;          /* model's polygons */
};

/*** An OBJ model ***/
struct obj_model_t objfile;


/**
* Free resources allocated for the model.
*/
void
FreeModel (struct obj_model_t *mdl)
{
	int i;

	if (mdl)
	{
		if (mdl->vertices)
		{
			free (mdl->vertices);
			mdl->vertices = NULL;
		}

		if (mdl->texCoords)
		{
			free (mdl->texCoords);
			mdl->texCoords = NULL;
		}

		if (mdl->normals)
		{
			free (mdl->normals);
			mdl->normals = NULL;
		}

		if (mdl->faces)
		{
			for (i = 0; i < mdl->num_faces; ++i)
			{
				if (mdl->faces[i].vert_indices)
					free (mdl->faces[i].vert_indices);

				if (mdl->faces[i].uvw_indices)
					free (mdl->faces[i].uvw_indices);

				if (mdl->faces[i].norm_indices)
					free (mdl->faces[i].norm_indices);
			}

			free (mdl->faces);
			mdl->faces = NULL;
		}
	}
}

/**
* Allocate resources for the model after first pass.
*/
int
MallocModel (struct obj_model_t *mdl)
{
	if (mdl->num_verts)
	{
		mdl->vertices = (struct obj_vertex_t *)
			malloc (sizeof (struct obj_vertex_t) * mdl->num_verts);
		if (!mdl->vertices)
			return 0;
	}

	if (mdl->num_texCoords)
	{
		mdl->texCoords = (struct obj_texCoord_t *)
			malloc (sizeof (struct obj_texCoord_t) * mdl->num_texCoords);
		if (!mdl->texCoords)
			return 0;
	}

	if (mdl->num_normals)
	{
		mdl->normals = (struct obj_normal_t *)
			malloc (sizeof (struct obj_normal_t) * mdl->num_normals);
		if (!mdl->normals)
			return 0;
	}

	if (mdl->num_faces)
	{
		mdl->faces = (struct obj_face_t *)
			calloc (mdl->num_faces, sizeof (struct obj_face_t));
		if (!mdl->faces)
			return 0;
	}

	return 1;
}

/**
* Load an OBJ model from file -- first pass.
* Get the number of triangles/vertices/texture coords for
* allocating buffers.
*/
int
FirstPass (FILE *fp, struct obj_model_t *mdl)
{
	int v, t, n;
	char buf[256];

	while (!feof (fp))
	{
		/* Read whole line */
		fgets (buf, sizeof (buf), fp);

		switch (buf[0])
		{
		case 'v':
			{
				if (buf[1] == ' ')
				{
					/* Vertex */
					mdl->num_verts++;
				}
				else if (buf[1] == 't')
				{
					/* Texture coords. */
					mdl->num_texCoords++;
				}
				else if (buf[1] == 'n')
				{
					/* Normal vector */
					mdl->num_normals++;
				}
				else
				{
					printf ("Warning: unknown token \"%s\"! (ignoring)\n", buf);
				}

				break;
			}

		case 'f':
			{
				/* Face */
				if (sscanf (buf + 2, "%d/%d/%d", &v, &n, &t) == 3)
				{
					mdl->num_faces++;
					mdl->has_texCoords = 1;
					mdl->has_normals = 1;
				}
				else if (sscanf (buf + 2, "%d//%d", &v, &n) == 2)
				{
					mdl->num_faces++;
					mdl->has_texCoords = 0;
					mdl->has_normals = 1;
				}
				else if (sscanf (buf + 2, "%d/%d", &v, &t) == 2)
				{
					mdl->num_faces++;
					mdl->has_texCoords = 1;
					mdl->has_normals = 0;
				}
				else if (sscanf (buf + 2, "%d", &v) == 1)
				{
					mdl->num_faces++;
					mdl->has_texCoords = 0;
					mdl->has_normals = 0;
				}
				else
				{
					/* Should never be there or the model is very crappy */
					fprintf (stderr, "Error: found face with no vertex!\n");
				}

				break;
			}

		case 'g':
			{
				/* Group */
				/*	fscanf (fp, "%s", buf); */
				break;
			}

		default:
			break;
		}
	}

	/* Check if informations are valid */
	if ((mdl->has_texCoords && !mdl->num_texCoords) ||
		(mdl->has_normals && !mdl->num_normals))
	{
		fprintf (stderr, "error: contradiction between collected info!\n");
		return 0;
	}

	if (!mdl->num_verts)
	{
		fprintf (stderr, "error: no vertex found!\n");
		return 0;
	}

	printf ("first pass results: found\n");
	printf ("   * %i vertices\n", mdl->num_verts);
	printf ("   * %i texture coords.\n", mdl->num_texCoords);
	printf ("   * %i normal vectors\n", mdl->num_normals);
	printf ("   * %i faces\n", mdl->num_faces);
	printf ("   * has texture coords.: %s\n", mdl->has_texCoords ? "yes" : "no");
	printf ("   * has normals: %s\n", mdl->has_normals ? "yes" : "no");

	return 1;
}

/**
* Load an OBJ model from file -- first pass.
* This time, read model data and feed buffers.
*/
int
SecondPass (FILE *fp, struct obj_model_t *mdl)
{
	struct obj_vertex_t *pvert = mdl->vertices;
	struct obj_texCoord_t *puvw = mdl->texCoords;
	struct obj_normal_t *pnorm = mdl->normals;
	struct obj_face_t *pface = mdl->faces;
	char buf[128], *pbuf;
	int i;

	while (!feof (fp))
	{
		/* Read whole line */
		fgets (buf, sizeof (buf), fp);

		switch (buf[0])
		{
		case 'v':
			{
				if (buf[1] == ' ')
				{
					/* Vertex */
					if (sscanf (buf + 2, "%f %f %f %f",
						&pvert->xyzw[0], &pvert->xyzw[1],
						&pvert->xyzw[2], &pvert->xyzw[3]) != 4)
					{
						if (sscanf (buf + 2, "%f %f %f", &pvert->xyzw[0],
							&pvert->xyzw[1], &pvert->xyzw[2] ) != 3)
						{
							fprintf (stderr, "Error reading vertex data!\n");
							return 0;
						}
						else
						{
							pvert->xyzw[3] = 1.0;
						}
					}

					pvert++;
				}
				else if (buf[1] == 't')
				{
					/* Texture coords. */
					if (sscanf (buf + 2, "%f %f %f", &puvw->uvw[0],
						&puvw->uvw[1], &puvw->uvw[2]) != 3)
					{
						if (sscanf (buf + 2, "%f %f", &puvw->uvw[0],
							&puvw->uvw[1]) != 2)
						{
							if (sscanf (buf + 2, "%f", &puvw->uvw[0]) != 1)
							{
								fprintf (stderr, "Error reading texture coordinates!\n");
								return 0;
							}
							else
							{
								puvw->uvw[1] = 0.0;
								puvw->uvw[2] = 0.0;
							}
						}
						else
						{
							puvw->uvw[2] = 0.0;
						}
					}

					puvw++;
				}
				else if (buf[1] == 'n')
				{
					/* Normal vector */
					if (sscanf (buf + 2, "%f %f %f", &pnorm->ijk[0],
						&pnorm->ijk[1], &pnorm->ijk[2]) != 3)
					{
						fprintf (stderr, "Error reading normal vectors!\n");
						return 0;
					}

					pnorm++;
				}

				break;
			}

		case 'f':
			{
				pbuf = buf;
				pface->num_elems = 0;

				/* Count number of vertices for this face */
				while (*pbuf)
				{
					if (*pbuf == ' ')
						pface->num_elems++;

					pbuf++;
				}

				/* Select primitive type */
				if (pface->num_elems < 3)
				{
					fprintf (stderr, "Error: a face must have at least 3 vertices!\n");
					return 0;
				}
				else if (pface->num_elems == 3)
				{
					pface->type = GL_TRIANGLES;
				}
				else if (pface->num_elems == 4)
				{
					pface->type = GL_QUADS;
				}
				else
				{
					pface->type = GL_POLYGON;
				}

				/* Memory allocation for vertices */
				pface->vert_indices = (int *)malloc (sizeof (int) * pface->num_elems);

				if (mdl->has_texCoords)
					pface->uvw_indices = (int *)malloc (sizeof (int) * pface->num_elems);

				if (mdl->has_normals)
					pface->norm_indices = (int *)malloc (sizeof (int) * pface->num_elems);

				/* Read face data */
				pbuf = buf;
				i = 0;

				for (i = 0; i < pface->num_elems; ++i)
				{
					pbuf = strchr (pbuf, ' ');
					pbuf++; /* Skip space */

					/* Try reading vertices */
					if (sscanf (pbuf, "%d/%d/%d",
						&pface->vert_indices[i],
						&pface->uvw_indices[i],
						&pface->norm_indices[i]) != 3)
					{
						if (sscanf (pbuf, "%d//%d", &pface->vert_indices[i],
							&pface->norm_indices[i]) != 2)
						{
							if (sscanf (pbuf, "%d/%d", &pface->vert_indices[i],
								&pface->uvw_indices[i]) != 2)
							{
								sscanf (pbuf, "%d", &pface->vert_indices[i]);
							}
						}
					}

					/* Indices must start at 0 */
					pface->vert_indices[i]--;

					if (mdl->has_texCoords)
						pface->uvw_indices[i]--;

					if (mdl->has_normals)
						pface->norm_indices[i]--;
				}

				pface++;
				break;
			}
		}
	}

	printf ("second pass results: read\n");
	printf ("   * %i vertices\n", pvert - mdl->vertices);
	printf ("   * %i texture coords.\n", puvw - mdl->texCoords);
	printf ("   * %i normal vectors\n", pnorm - mdl->normals);
	printf ("   * %i faces\n", pface - mdl->faces);

	return 1;
}

/**
* Load an OBJ model from file, in two passes.
*/
int
ReadOBJModel (const char *filename, struct obj_model_t *mdl)
{
	FILE *fp;

	fp = fopen (filename, "r");
	if (!fp)
	{
		fprintf (stderr, "Error: couldn't open \"%s\"!\n", filename);
		return 0;
	}

	/* reset model data */
	memset (mdl, 0, sizeof (struct obj_model_t));

	/* first pass: read model info */
	if (!FirstPass (fp, mdl))
	{
		fclose (fp);
		return 0;
	}

	rewind (fp);

	/* memory allocation */
	if (!MallocModel (mdl))
	{
		fclose (fp);
		FreeModel (mdl);
		return 0;
	}

	/* second pass: read model data */
	if (!SecondPass (fp, mdl))
	{
		fclose (fp);
		FreeModel (mdl);
		return 0;
	}

	fclose (fp);
	return 1;
}

/**
* Draw the OBJ model.
*/
void
RenderOBJModel (struct obj_model_t *mdl)
{
	int i, j;

	for (i = 0; i < mdl->num_faces; ++i)
	{
		glBegin (mdl->faces[i].type);
		for (j = 0; j < mdl->faces[i].num_elems; ++j)
		{
			if (mdl->has_texCoords)
				glTexCoord3fv (mdl->texCoords[mdl->faces[i].uvw_indices[j]].uvw);

			if (mdl->has_normals)
				glNormal3fv (mdl->normals[mdl->faces[i].norm_indices[j]].ijk);

			glVertex4fv (mdl->vertices [mdl->faces[i].vert_indices[j]].xyzw);
		}
		glEnd();
	}
}
/* obj loader ends here */

void initGame()
{
	srand((unsigned)time( NULL ) );
	//OpenGL setup
	glClearColor(0.3, 0.0, 0.5, 0.0);

	GLfloat ambient[] = {1.0, 1.0, 1.0, 1.0};
	GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
	GLfloat specular[] = {1.0, 0.5, 0.5, 1.0};
	GLfloat position[] = {1.0, 1.0, 1.0, 0.0};
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
	glLightfv(GL_LIGHT0, GL_POSITION, position);
	///GLfloat lightPos[] = {0.0, 0.0, 0.0, 1.0};
	//glLightfv(GL_LIGHT1, GL_POSITION, lightPos);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	//glEnable(GL_LIGHT1);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);

	//Game setup
	int i, j;
	for (i=0; i < k_numRows; i++)
	{
		for (j=0; j < k_numCols; j++)
		{
			g_grid[i][j] = new CPiece(i, j);
		}
	}
	g_firstPiece = NULL;

	while (findMatches().size() > 0) // matches available which shouldn't be there
	{
		for (i=0; i < k_numRows; i++)
		{
			for (j=0; j < k_numCols; j++)
			{
				//pick a new random type
				g_grid[i][j]->chooseType();
			}
		}
	}

	//Set up models
	/****** Fighter Model *******/

	g_pTextureLoader->LoadTextureFromDisk("fighter_texture.jpg", &g_fighterTexture);

	glBindTexture(GL_TEXTURE_2D, g_fighterTexture.TextureID);

	//set up display lists
	g_fighterList = glGenLists(1);

	glNewList(g_fighterList, GL_COMPILE);

	glScalef(0.08, 0.08, 0.08);
	glRotatef(45.0, 1.0, 0.0, 0.0);

	/* Load OBJ model file */
	if (!ReadOBJModel ("fighter.obj", &objfile))
		exit (EXIT_FAILURE);

	RenderOBJModel(&objfile);

	glEndList();

	/****** Knight Model *******/

	g_pTextureLoader->LoadTextureFromDisk("chevalier.bmp", &g_knightTexture);

	glBindTexture(GL_TEXTURE_2D, g_knightTexture.TextureID);

	//set up display lists
	g_knightList = glGenLists(1);

	glNewList(g_knightList, GL_COMPILE);

	glScalef(0.08, 0.08, 0.08);
	glTranslatef(0.0, -0.5, 0.0);

	/* Load OBJ model file */
	if (!ReadOBJModel ("chevalier.obj", &objfile))
		exit (EXIT_FAILURE);

	RenderOBJModel(&objfile);

	glEndList();

	/****** propeller Model *******/

	g_pTextureLoader->LoadTextureFromDisk("wood7.jpg", &g_propellerTexture);

	glBindTexture(GL_TEXTURE_2D, g_propellerTexture.TextureID);

	//set up display lists
	g_propellerList = glGenLists(1);

	glNewList(g_propellerList, GL_COMPILE);

	//glScalef(0.5, 0.5, 0.5);

	/* Load OBJ model file */
	if (!ReadOBJModel ("propeller.obj", &objfile))
		exit (EXIT_FAILURE);

	RenderOBJModel(&objfile);

	glEndList();

	/****** Guitar Pick Model *******/

	g_pTextureLoader->LoadTextureFromDisk("picksalot2.jpg", &g_pickTexture);

	glBindTexture(GL_TEXTURE_2D, g_pickTexture.TextureID);

	//set up display lists
	g_pickList = glGenLists(1);

	glNewList(g_pickList, GL_COMPILE);

	glScalef(0.001, 0.01, 0.01);

	/* Load OBJ model file */
	if (!ReadOBJModel ("guitarpick.obj", &objfile))
		exit (EXIT_FAILURE);

	RenderOBJModel(&objfile);

	glEndList();

	/****** Car Model *******/

	g_pTextureLoader->LoadTextureFromDisk("HyundaiSantaFe.bmp", &g_carTexture);

	glBindTexture(GL_TEXTURE_2D, g_carTexture.TextureID);

	//set up display lists
	g_carList = glGenLists(1);

	glNewList(g_carList, GL_COMPILE);

	glScalef(0.008, 0.008, 0.008);
	glRotatef(180.0, 0.0, 1.0, 0.0);

	/* Load OBJ model file */
	if (!ReadOBJModel ("santaFe.obj", &objfile))
		exit (EXIT_FAILURE);

	RenderOBJModel(&objfile);

	glEndList();

	/****** Video Wall Model *******/

	g_pTextureLoader->LoadTextureFromDisk("rice.jpg", &g_killnerTexture);

	glBindTexture(GL_TEXTURE_2D, g_killnerTexture.TextureID);

	//set up display lists
	g_killnerList = glGenLists(1);

	glNewList(g_killnerList, GL_COMPILE);

	glScalef(0.005, 0.005, 0.005);
	glTranslatef(0.0, 0.3, 0.0);


	/* Load OBJ model file */
	if (!ReadOBJModel ("kilner_contents.obj", &objfile))
		exit (EXIT_FAILURE);

	RenderOBJModel(&objfile);

	glEndList();
}



void draw()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);

	for (int i=0; i < k_numRows; i++)
	{
		for (int j=0; j < k_numCols; j++)
		{
			g_grid[i][j]->draw();
		}
	}

	glFlush();
}

void reshape(int width, int height)
{

}

vector<CPiece *> findHorizMatches(int row, int col)
{
	vector<CPiece*> horizmatches;
	for (int i=0; (col + i) < k_numCols; i++)
	{
		if (g_grid[row][col]->getType() == g_grid[row][col+i]->getType())
		{
			horizmatches.push_back(g_grid[row][col+i]);
		} else {
			return horizmatches;
		}
	}
	return horizmatches;
}

vector<CPiece *> findVertMatches(int row, int col)
{
	vector<CPiece*> vertmatches;
	for (int i=0; (row + i) < k_numRows; i++)
	{
		if (g_grid[row][col]->getType() == g_grid[row+i][col]->getType())
		{
			vertmatches.push_back(g_grid[row+i][col]);
		} else {
			return vertmatches;
		}
	}
	return vertmatches;
}

vector<CPiece *> findMatches()
{
	vector<CPiece *> matches;

	//Find horizontal matches
	for (int i=0; i < k_numRows; i++)
	{
		for (int j=0; j < (k_numCols - 2); j++)
		{
			vector<CPiece*>hmatch = findHorizMatches(i, j);
			if (hmatch.size() > 2)
			{
				int vhsize = (int) hmatch.size();
				for (int k=0; k < vhsize; k++)
				{
					matches.push_back(hmatch[k]);
					j += vhsize - 1;
				}
			}
		}
	}

	//find vertical matches
	for (int i=0; i < k_numCols; i++)
	{
		for (int j=0; j < (k_numRows - 2); j++)
		{
			vector<CPiece*>vmatch = findVertMatches(j, i);
			if (vmatch.size() > 2)
			{
				int vvsize = (int) vmatch.size();
				for (int k=0; k < vvsize; k++)
				{
					matches.push_back(vmatch[k]);
					j += vvsize - 1;
				}
			}
		}
	}

	return matches;
}

void affectAbove(CPiece* p)
{
	for (int i = (p->getRow() + 1); i < k_numRows; i++)
	{
		if (g_grid[i][p->getCol()] != NULL)
		{
			g_grid[i][p->getCol()]->setRow(i-1);
			g_grid[i-1][p->getCol()] = g_grid[i][p->getCol()];
			g_grid[i][p->getCol()] = NULL;
		}
	}
}

void addNewPieces()
{
	for (int i = 0; i < k_numRows; i++)
	{
		for (int j = 0; j < k_numCols; j++)
		{
			if (g_grid[i][j] == NULL)
			{
				g_grid[i][j] = new CPiece(i, j);
			}
		}
	}
}

void findAndRemoveMatches()
{
	vector<CPiece*> matches = findMatches();
	vector<CPiece*> matchesToDelete;

	while (matches.size() > 0)
	{
		for (unsigned int i=0; i<matches.size(); i++)
		{
			g_grid[matches[i]->getRow()][matches[i]->getCol()] = NULL;
			affectAbove(matches[i]);
			bool alreadyBeingDeleted = false;
			for (unsigned int j=0; j<matchesToDelete.size(); j++)
			{
				if ((matches[i]->getCol() == matchesToDelete[j]->getCol()) && (matches[i]->getRow() == matchesToDelete[j]->getRow()))
				{
					alreadyBeingDeleted = true;
				}
			}
			if (alreadyBeingDeleted == false)
			{
				matchesToDelete.push_back(matches[i]);
			}
		}


		addNewPieces();
		draw();
		matches = findMatches();
	}
	for (unsigned int i=0; i<matchesToDelete.size(); i++)
	{
		if (matchesToDelete[i])
		{
			delete matchesToDelete[i];
			matchesToDelete[i] = NULL;
		}
	}
	matchesToDelete.clear();
}

void swapPieces(CPiece* piece1, CPiece* piece2)
{
	int temprow, tempcol;
	tempcol = piece1->getCol();
	temprow = piece1->getRow();
	piece1->setCol(piece2->getCol());
	piece1->setRow(piece2->getRow());
	g_grid[g_firstPiece->getRow()][g_firstPiece->getCol()] = piece1;
	piece2->setCol(tempcol);
	piece2->setRow(temprow);
	g_grid[piece2->getRow()][piece2->getCol()] = piece2;
	draw();
}

void makeSwap(CPiece* piece1, CPiece* piece2)
{
	swapPieces(piece1, piece2);

	if (findMatches().size() == 0)
	{
		swapPieces(piece1, piece2);
	} else {
		findAndRemoveMatches();
	}
}

void handleMouse(int button, int state, int x, int y)
{
	int row_height, col_width;
	int newx, newy;
	CPiece* clickedPiece;
	if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)
		return;

	row_height = k_grid_height / k_numRows;
	col_width = k_grid_width / k_numCols;
	newx = x;
	newy = k_grid_height - y;

	for (int i = 0; i < k_numRows; i++)
	{
		for (int j = 0; j < k_numCols; j++)
		{
			if ((newy > (i * row_height)) && (newy < ((i + 1)* row_height)) && (newx > (j * col_width)) && (newx < (j + 1) * col_width))
			{
				clickedPiece = g_grid[i][j];
				break;
			}
		}
	}

	if (g_firstPiece == NULL) 
	{
		g_firstPiece = clickedPiece;
	//} else if (g_firstPiece = clickedPiece) 
	//{
		//clicked again to deselect it
	//	g_firstPiece = NULL;
	} else 
	{
		if (g_firstPiece->getRow() == clickedPiece->getRow()) 
		{
			if (abs(g_firstPiece->getCol() - clickedPiece->getCol()) == 1)
			{
				makeSwap(g_firstPiece, clickedPiece);
				g_firstPiece = NULL;
			}
		} else if (g_firstPiece->getCol() == clickedPiece->getCol())
		{
			if (abs(g_firstPiece->getRow() - clickedPiece->getRow()) == 1)
			{
				makeSwap(g_firstPiece, clickedPiece);
				g_firstPiece = NULL;
			}
		}
	}
}

void handleKeyboard(unsigned char key, int x, int y)
{
	switch(key)
	{
	case 27:
		g_pTextureLoader->FreeTexture(&g_fighterTexture);
		glDeleteLists(g_fighterList, 1);
		g_pTextureLoader->FreeTexture(&g_knightTexture);
		glDeleteLists(g_knightList, 1);
		g_pTextureLoader->FreeTexture(&g_propellerTexture);
		glDeleteLists(g_propellerList, 1);
		g_pTextureLoader->FreeTexture(&g_pickTexture);
		glDeleteLists(g_pickList, 1);
		g_pTextureLoader->FreeTexture(&g_carTexture);
		glDeleteLists(g_carList, 1);
		g_pTextureLoader->FreeTexture(&g_killnerTexture);
		glDeleteLists(g_killnerList, 1);

		for (int i = 0; i < k_numRows; i++)
		{
			for (int j = 0; j < k_numCols; j++)
			{
				if (g_grid[i][j] == NULL)
				{
					delete g_grid[i][j];
				}
			}
		}
		exit(0);
		break;
	}
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(k_grid_width, k_grid_height);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Random Objects Match 3");
	initGame();
	glutDisplayFunc(draw);
	glutReshapeFunc(reshape);
	glutMouseFunc(handleMouse);
	glutKeyboardFunc(handleKeyboard);
	glutMainLoop();
	return 0;
}