// This function reads a modified 3d data file exported by 3D Exploration. 

#define LINE_BUF_SIZE 2000
#define FILE_BUF_SIZE 10000000

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL\gl.h>
#include <GL\glu.h>
#include <gl\glut.h>

typedef struct {
 GLfloat ambient[3];
 GLfloat diffuse[3];
 GLfloat specular[3];
 GLfloat emission[3];
 GLfloat alpha;
 GLfloat phExp;
 int   texture;
}sample_MATERIAL;

typedef struct {
 char * name;
 GLint  id;
}sample_TEXTURE;

void ParseObjectFile(char *filename, sample_MATERIAL **materials, sample_TEXTURE **texture_maps, short ***face_indicies, GLfloat ***vertices, GLfloat ***normals, GLfloat ***textures, int ***material_ref, int *num_triangles, int *num_texturemaps)
{
	int num_materials, row_max, col_max;
	char line_buffer[LINE_BUF_SIZE], *file_buffer, *number;
	FILE *infile, *outfile;
	
	infile = fopen(filename, "r");
	outfile = fopen("filebuffer", "w"); // this file buffer is created for reading in data

	file_buffer = (char *)malloc(sizeof(char) * FILE_BUF_SIZE);
	if (infile == NULL)
	{
		printf("Cannot open %s.", filename);
		return;
	}

	if (outfile == NULL)
	{
		printf("Cannot create file buffer.");
		return;
	}

	while (fgets(line_buffer, LINE_BUF_SIZE, infile) != NULL) {
		number = strtok(line_buffer, "{,}; \t\n");
		while (number != NULL)
		{
			if ((number[0] == '/') && (number[1] == '/')) break; // in case it's a comment go to the next line
			fprintf(outfile, "%s ", number);
			number = strtok(NULL, "{,}; \t\n");
		}
	}

	fclose(infile);
	fclose(outfile);

	// now that i've made "filebuffer" which is easier to read, let's parse it, baby
	infile = fopen("filebuffer", "r");
	fgets(file_buffer, FILE_BUF_SIZE, infile);
	number = strtok(file_buffer, " ");

	if (strcmp(number, "materials") == 0)
	{
		number = strtok(NULL, " ");
		num_materials = atoi(number);
		*materials = (sample_MATERIAL *)malloc(sizeof(sample_MATERIAL)*num_materials);
		for (int i=0; i < num_materials; i++)
		{
			(*materials)[i].ambient[0] = atof(strtok(NULL, " "));
			(*materials)[i].ambient[1] = atof(strtok(NULL, " "));
			(*materials)[i].ambient[2] = atof(strtok(NULL, " "));
			(*materials)[i].diffuse[0] = atof(strtok(NULL, " "));
			(*materials)[i].diffuse[1] = atof(strtok(NULL, " "));
			(*materials)[i].diffuse[2] = atof(strtok(NULL, " "));
			(*materials)[i].specular[0] = atof(strtok(NULL, " "));
			(*materials)[i].specular[1] = atof(strtok(NULL, " "));
			(*materials)[i].specular[2] = atof(strtok(NULL, " "));
			(*materials)[i].emission[0] = atof(strtok(NULL, " "));
			(*materials)[i].emission[1] = atof(strtok(NULL, " "));
			(*materials)[i].emission[2] = atof(strtok(NULL, " "));
			(*materials)[i].alpha = atof(strtok(NULL, " "));
			(*materials)[i].phExp = atof(strtok(NULL, " "));
			(*materials)[i].texture = atoi(strtok(NULL, " "));
		}
	} else { printf("Error reading materials!");}


				// testing parsing the material segment
				/*
				for (int i=0; i < num_materials; i++)
				{
					printf("%f ", (*materials)[i].ambient[0]);
					printf("%f ", (*materials)[i].ambient[1]);
					printf("%f ", (*materials)[i].ambient[2]);
					printf("%f ", (*materials)[i].diffuse[0]);
					printf("%f ", (*materials)[i].diffuse[1]);
					printf("%f ", (*materials)[i].diffuse[2]);
					printf("%f ", (*materials)[i].specular[0]);
					printf("%f ", (*materials)[i].specular[1]);
					printf("%f ", (*materials)[i].specular[2]);
					printf("%f ", (*materials)[i].emission[0]);
					printf("%f ", (*materials)[i].emission[1]);
					printf("%f ", (*materials)[i].emission[2]);
					printf("%f ", (*materials)[i].alpha);
					printf("%f ", (*materials)[i].phExp);
					printf("%d ", (*materials)[i].texture);
				}*/


	number = strtok(NULL, " ");
	if (strcmp(number, "texture_maps") == 0)
	{	
		number = strtok(NULL, " ");
		*num_texturemaps = atoi(number);
		*texture_maps = (sample_TEXTURE *)malloc(sizeof(sample_TEXTURE) * (*num_texturemaps));
		for (int i=0; i < *num_texturemaps; i++)
		{
			(*texture_maps)[i].name = strtok(NULL, " \"");
			(*texture_maps)[i].id = atoi(strtok(NULL, " "));
		}
	} else { printf("Error reading texture_maps!");}


				// testing parsing the material segment
				/*
				printf("%d", num_texturemaps);
				for (int i=0; i < num_texturemaps; i++)
				{
					printf("%s ", texture_maps[i].name);
					printf("%d ", texture_maps[i].id );
				}
				*/


	number = strtok(NULL, " ");
	if (strcmp(number, "face_indicies") == 0)
	{	
		number = strtok(NULL, " ");
		row_max = atoi(number);
		*num_triangles = row_max;
		number = strtok(NULL, " ");
		col_max = atoi(number);

		// allocate memory for face_indicies
		*face_indicies = (short **)malloc(sizeof(short *) * row_max);
		for (int k=0; k < row_max; k++)
		{
			(*face_indicies)[k] = (short *) malloc(sizeof(short) * col_max);
		}
		
		for (int i=0; i < row_max; i++)
		{
			for (int j=0; j < col_max; j++)
			{
				(*face_indicies)[i][j] = atoi(strtok(NULL, " "));
			}
		}
	} else { printf("Error reading face_indicies!");}


				// testing parsing the face_indicies segment
				/*
				for (int i=0; i < row_max; i++)
				{
					for (int j=0; j < col_max; j++)
					{
						printf("%d ", face_indicies[i][j]);
					}
				}
				*/

	number = strtok(NULL, " ");
	if (strcmp(number, "vertices") == 0)
	{	
		number = strtok(NULL, " ");
		row_max = atoi(number);
		number = strtok(NULL, " ");
		col_max = atoi(number);

		// allocate memory for vertices
		*vertices = (GLfloat **)malloc(sizeof(GLfloat *) * row_max);
		for (int k=0; k < row_max; k++)
		{
			(*vertices)[k] = (GLfloat *) malloc(sizeof(GLfloat) * col_max);
		}
		
		for (int i=0; i < row_max; i++)
		{
			for (int j=0; j < col_max; j++)
			{
				(*vertices)[i][j] = atof(strtok(NULL, " "));
			}
		}
	} else { printf("Error reading vertices!");}


				// testing parsing the vertices segment
				/*
				for (int i=0; i < row_max; i++)
				{
					for (int j=0; j < col_max; j++)
					{
						printf("%f ", vertices[i][j]);
					}
				}
				*/


	number = strtok(NULL, " ");
	if (strcmp(number, "normals") == 0)
	{	
		number = strtok(NULL, " ");
		row_max = atoi(number);
		number = strtok(NULL, " ");
		col_max = atoi(number);

		// allocate memory for normals
		*normals = (GLfloat **)malloc(sizeof(GLfloat *) * row_max);
		for (int k=0; k < row_max; k++)
		{
			(*normals)[k] = (GLfloat *) malloc(sizeof(GLfloat) * col_max);
		}
		
		for (int i=0; i < row_max; i++)
		{
			for (int j=0; j < col_max; j++)
			{
				(*normals)[i][j] = atof(strtok(NULL, " "));
			}
		}
	} else { printf("Error reading normals!");}


				// testing parsing the normals segment
				/*
				for (int i=0; i < row_max; i++)
				{
					for (int j=0; j < col_max; j++)
					{
						printf("%f ", normals[i][j]);
					}
				}
				*/


	number = strtok(NULL, " ");
	if (strcmp(number, "textures") == 0)
	{	
		number = strtok(NULL, " ");
		row_max = atoi(number);
		number = strtok(NULL, " ");
		col_max = atoi(number);

		// allocate memory for textures
		*textures = (GLfloat **)malloc(sizeof(GLfloat *) * row_max);
		for (int k=0; k < row_max; k++)
		{
			(*textures)[k] = (GLfloat *) malloc(sizeof(GLfloat) * col_max);
		}
		
		for (int i=0; i < row_max; i++)
		{
			for (int j=0; j < col_max; j++)
			{
				(*textures)[i][j] = atof(strtok(NULL, " "));
			}
		}
	} else { printf("Error reading textures!");}

	
				// testing parsing the textures segment
				
				/*
				for (int i=0; i < row_max; i++)
				{
					for (int j=0; j < col_max; j++)
					{
						printf("%f ", textures[i][j]);
					}
				}
				*/


	number = strtok(NULL, " ");
	if (strcmp(number, "material_ref") == 0)
	{	
		number = strtok(NULL, " ");
		row_max = atoi(number);
		number = strtok(NULL, " ");
		col_max = atoi(number);

		// allocate memory for material_ref
		*material_ref = (int **)malloc(sizeof(int *) * row_max);
		for (int k=0; k < row_max; k++)
		{
			(*material_ref)[k] = (int *) malloc(sizeof(int) * col_max);
		}
		
		for (int i=0; i < row_max; i++)
		{
			for (int j=0; j < col_max; j++)
			{
				(*material_ref)[i][j] = atoi(strtok(NULL, " "));
			}
		}
	} else { printf("Error reading material_ref!");}

				// testing parsing the material_ref segment
				
				/*
				for (int i=0; i < row_max; i++)
				{
					for (int j=0; j < col_max; j++)
					{
						printf("%d ", material_ref[i][j]);
					}
				}
				*/

	fclose(infile);
}