/*
Solar Conquest
Copyright (C) 2006 Greg Beaman

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

struct shape_tri
{
	int p1, p2, p3;
};
struct shape_line
{
	int p1, p2;
};
struct model_point
{
	float angle;
	float dist;
};

using namespace std;

class CModel
{
private:
	int numPoints;
	model_point* points;
	Vector* vpoints; //used so we only have to calculate point positions once while rendering!
	int numTris;
	shape_tri* tris;
	int numLines;
	shape_line* lines;

	bool loaded;
public:
	CModel();
	~CModel();

	void UnloadModel();
	void LoadModel(char* fileName);

	bool HasLoaded();
	
	void Render(Vector position, float angle);
};

CModel::CModel()
{
	loaded = false;
	points = NULL;
	vpoints = NULL;
	tris = NULL;
	lines = NULL;
}

CModel::~CModel()
{
	UnloadModel();
}

void CModel::UnloadModel()
{
	if (loaded)
	{
		free(points);
		free(vpoints);
		free(tris);
		free(lines);
		
		points = NULL;
		vpoints = NULL;
		tris = NULL;
		lines = NULL;
		loaded = false;
	}
}
/*			   *
 * WINDOWS FIX *
 *			   */
void CModel::LoadModel(char* fileName)
{
	if (loaded)
		UnloadModel();

	printf("Loading model ");
	printf(fileName);
	printf("\n");
	if (!FileExists(fileName))
	{
		DebugMessage(1,"ERROR! COULD NOT OPEN FILE!");
		return;
	}
	ifstream file;
	file.open(fileName);

	//Get the number of points, triangles, and lines out of the file
	//we put this data in ahead of time so we can abort early if there's an invalid value
	file >> numPoints >> numTris >> numLines;
	if (numPoints < 3 || numPoints > 255 || numTris < 1 || numTris > 255 || numLines < 1 || numLines > 255)
	{
		DebugMessage(1,"ERROR! Invalid number for points/tris/lines...");
		file.close();
		return;
	}
		
	//Allocate memory for the points, tris, and lines
	points = (model_point*)malloc(sizeof(model_point)*numPoints);
	if (!points)
		return;
	vpoints = (Vector*)malloc(sizeof(Vector)*numPoints);
	if (!vpoints)
	{
		free(points);
		return;
	}
	tris = (shape_tri*)malloc(sizeof(shape_tri)*numTris);
	if (!tris)
	{
		free(points);
		free(vpoints);
		return;
	}
	lines = (shape_line*)malloc(sizeof(shape_line)*numLines);
	if (!lines)
	{
		free(points);
		free(vpoints);
		free(tris);
		return;
	}
		
	//Load the vectors out of the file!
	{
	for (int i=0; i < numPoints; i++)
		file >> points[i].angle >> points[i].dist;
	}
	int p1,p2,p3;
	{
	for (int i=0; i < numTris; i++)
	{
		file >> p1 >> p2 >> p3;
		if (p1 > -1 && p1 < numPoints)
			tris[i].p1 = p1;
		else
			tris[i].p1 = 0;
		if (p2 > -1 && p2 < numPoints)
			tris[i].p2 = p2;
		else
			tris[i].p2 = 0;
		if (p3 > -1 && p3 < numPoints)
			tris[i].p3 = p3;
		else
			tris[i].p3 = 0;
	}
	}
	{
	for (int i=0; i < numLines; i++)
	{
		file >> p1 >> p2;
		if (p1 > -1 && p1 < numPoints)
			lines[i].p1 = p1;
		else
			lines[i].p1 = 0;
		if (p2 > -1 && p2 < numPoints)
			lines[i].p2 = p2;
		else
			lines[i].p2 = 0;
	}
	}

	file.close();
	
	loaded = true;
}
/*
void CModel::LoadModel(char* fileName)
{
	if (loaded)
		UnloadModel();

	printf("Loading model ");
	printf(fileName);
	printf("\n");
	if (!FileExists(fileName))
	{
		DebugMessage(1,"ERROR! COULD NOT OPEN FILE!");
		return;
	}
	ifstream file;
	file.open(fileName);

	//Get the number of points, triangles, and lines out of the file
	//we put this data in ahead of time so we can abort early if there's an invalid value
	file >> numPoints >> numTris >> numLines;
	if (numPoints < 3 || numPoints > 255 || numTris < 1 || numTris > 255 || numLines < 1 || numLines > 255)
	{
		DebugMessage(1,"ERROR! Invalid number for points/tris/lines...");
		file.close();
		return;
	}
		
	//Allocate memory for the points, tris, and lines
	points = (model_point*)malloc(sizeof(model_point)*numPoints);
	if (!points)
		return;
	vpoints = (Vector*)malloc(sizeof(Vector)*numPoints);
	if (!vpoints)
	{
		free(points);
		return;
	}
	tris = (shape_tri*)malloc(sizeof(shape_tri)*numTris);
	if (!tris)
	{
		free(points);
		free(vpoints);
		return;
	}
	lines = (shape_line*)malloc(sizeof(shape_line)*numLines);
	if (!lines)
	{
		free(points);
		free(vpoints);
		free(tris);
		return;
	}
		
	//Load the vectors out of the file!
	for (int i=0; i < numPoints; i++)
		file >> points[i].angle >> points[i].dist;
	int p1,p2,p3;
	for (i=0; i < numTris; i++)
	{
		file >> p1 >> p2 >> p3;
		if (p1 > -1 && p1 < numPoints)
			tris[i].p1 = p1;
		else
			tris[i].p1 = 0;
		if (p2 > -1 && p2 < numPoints)
			tris[i].p2 = p2;
		else
			tris[i].p2 = 0;
		if (p3 > -1 && p3 < numPoints)
			tris[i].p3 = p3;
		else
			tris[i].p3 = 0;
	}
	for (i=0; i < numLines; i++)
	{
		file >> p1 >> p2;
		if (p1 > -1 && p1 < numPoints)
			lines[i].p1 = p1;
		else
			lines[i].p1 = 0;
		if (p2 > -1 && p2 < numPoints)
			lines[i].p2 = p2;
		else
			lines[i].p2 = 0;
	}
	
	file.close();
	
	loaded = true;
}
*/
bool CModel::HasLoaded() { return loaded; }

void CModel::Render(Vector position, float angle)
{
	if (!loaded)
		return;
	{
	for (int i=0; i < numPoints; i++)
	{
		vpoints[i].x = (GetSin(angle-points[i].angle)*points[i].dist) + position.x;
		vpoints[i].y = (GetCos(angle-points[i].angle)*points[i].dist) + position.y;
	}
	}
	
	glBegin(GL_TRIANGLES);
		{
		for (int i=0; i < numTris; i++)
		{
			glVertex2f(vpoints[tris[i].p1].x,vpoints[tris[i].p1].y);
			glVertex2f(vpoints[tris[i].p2].x,vpoints[tris[i].p2].y);
			glVertex2f(vpoints[tris[i].p3].x,vpoints[tris[i].p3].y);
		}
		}
	glEnd();
	glBegin(GL_LINES);
		{
		for (int i=0; i < numLines; i++)
		{
			glVertex2f(vpoints[lines[i].p1].x,vpoints[lines[i].p1].y);
			glVertex2f(vpoints[lines[i].p2].x,vpoints[lines[i].p2].y);
		}
		}
	glEnd();
}
