#include "string.h"
#include "stdio.h"
#include "malloc.h"
#include "stdlib.h" 


typedef struct GROUP_TAG {
    char name[100];
    int id;
    int fnum;
    int FirstFace;
} Group;

typedef int VIndex[3];
typedef VIndex *Face;
typedef float Vert[3]; 

static int GGnum = 0;
static int GVnum = 0;
static int GVnnum = 0;
static int GFnum = 0;
static int GPrevGroup = 0;
static int GCurrGroup = 0;
static int GCurrGroupOpen = 0;
static Group *GGroups;
static Vert *GVerts;
static Vert *GNverts;

static void Pass1(FILE *);
static Vert *Add100(Vert **old, int items);
static int strwrd(char * line);

/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
/* HHHHH     add100           HHHHH */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
static Vert *Add100(Vert **old, int items)
{
    if (*old == NULL)
	*old = (Vert *) malloc((items + 102) * sizeof(Vert));
    else
	*old = (Vert *) realloc((char *) *old, (items + 102) * sizeof(Vert));

    if (*old == NULL) {   
	fprintf(stderr, "wf2irit: memory allocation failed\n");
	exit(1);
    }

    return *old;
}

/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
/* HHHHH     main             HHHHH */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
main(int argc,char * argv[])
{
    FILE * ifile;
    int i;
    int flag;
    char **DataFileNames;

    DataFileNames = argv + 1;
    flag = argc - 1;

    for (i = 0; i < argc - 1 || !flag; i++) {
	if (!flag) {
	    ifile = stdin;
	    flag = !flag;
	}
	else {
	    fprintf(stderr, "Processing \"%s\"\n", *DataFileNames);
	    if ((ifile = fopen(*DataFileNames, "r")) == NULL) {   
		fprintf(stderr, "Can't open data file %s.\n", *DataFileNames);
		exit(1);
	    }
	}

	GVerts = (Vert *) malloc(100 * sizeof(Vert));
	GNverts = (Vert *) malloc(100 * sizeof(Vert));

	GGnum = 0;
	GVnum = 0;
	GVnnum = 0;
	GFnum = 0;
	GPrevGroup = 0;
	GCurrGroup = 0;
	GCurrGroupOpen = 0;

	Pass1(ifile);

	free(GGroups);
	free(GVerts);
	free(GNverts);

	fclose(ifile);

	DataFileNames++;			  /* Skip to next file name. */
    }
}


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/* XXXXXXXX             Pass1                          XXXXXXXX */
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
static void Pass1(FILE *f)
{
    char Line[200];
    char FirstWord[20];

    while (!feof(f)) {
	fgets(Line, 100, f);
	if (strlen(Line) < 2)
	    continue;

	sscanf(Line, "%s", FirstWord);

	if (!strcmp(FirstWord,"g")) {
	    int i;
	    char gname[100];

	    if(GCurrGroupOpen) {
		fprintf(stdout,"] /* OBJECT %s */\n", 
			GGroups[GCurrGroup].name);
		GCurrGroupOpen = 0;
	    }

	    sscanf(Line, "g %s", gname);

	    /* Look for the groupname among already found. */

	    for (i=0; i<GGnum; i++)
	        if (!strcmp(GGroups[i].name, gname))
		    break;

	    if (i== GGnum) {
		/* If the found group is new. */
		if (GGroups == NULL)
		    GGroups = (Group *) malloc((GGnum +1) * sizeof(Group));
		else
		    GGroups = (Group *) realloc((char*)GGroups,
						(GGnum +1) * sizeof(Group));

		if (GGroups == NULL) {   
		    fprintf(stderr, "wf2irit: memory allocation failed\n");
		    exit(1);
		}

		strcpy(GGroups[GGnum].name,gname);
		GGroups[GGnum].id = GGnum;
		GGroups[GGnum].fnum = 0;
		GGroups[GGnum].FirstFace = GFnum;

		/* GPrevGroup = GCurrGroup; */
		GCurrGroup = GGnum;
		GGnum++;
	    }
	    else {
		/* The found group is already set. */
		if (GGroups[i].FirstFace == 0)
		    GGroups[i].FirstFace = GFnum;

		/* GPrevGroup = GCurrGroup; */
		GCurrGroup = i;
	    }
	}
	else if (!strcmp(FirstWord,"v")) {
	    if((GVnum - 99) % 100 == 0)
		Add100(&GVerts, GVnum);

	    {
		char t0[30];
		char t1[30];
		char t2[30];
		sscanf(Line,"v %s %s %s", t0, t1, t2);
		GVerts[GVnum][0] = atof(t0);
		GVerts[GVnum][1] = atof(t1);
		GVerts[GVnum][2] = atof(t2);
	    }
	    GVnum ++;
	}
	else if (!strcmp(FirstWord,"vn")) {
	    if((GVnnum - 99) % 100 == 0)
	        Add100(&GNverts,GVnnum);

	    {
		char t0[30];
		char t1[30];
		char t2[30];
		sscanf(Line,"v %s %s %s", t0, t1, t2);
		GNverts[GVnnum][0] = atof(t0);
		GNverts[GVnnum][1] = atof(t1);
		GNverts[GVnnum][2] = atof(t2);
	    }
	    GVnnum ++;
	}
	else if (!strcmp(FirstWord,"f") || !strcmp(FirstWord,"fo")) {
	    char * word;
	    char tmpLine[200];

	    /* 0 curr group need not to close prev. */
	    if (!GCurrGroupOpen) {
		fprintf(stdout,"[OBJECT   %s\n ",
			GGroups[GCurrGroup].name);
		GPrevGroup = GCurrGroup;
		GCurrGroupOpen = 1;
	    }

	    strcpy(tmpLine, Line);
	    fprintf(stdout,"\t[POLYGON %d\n",strwrd(tmpLine) - 1);
	    /* strwrd spoils the Line. */

	    strtok(Line," \t\n");
	    /* skip over 'f'. */
	    while ((word = strtok(NULL," \t\n")) != NULL) {
		int j, k;
		if(strchr(word,'/')) {
		    sscanf(word,"%d//%d",&j,&k);
		    printf("\t\t[[NORMAL %f %f %f] %f %f %f]\n",
			   GNverts[k-1][0],
			   GNverts[k-1][1],
			   GNverts[k-1][2],
			   GVerts[j-1][0],
			   GVerts[j-1][1],
			   GVerts[j-1][2]);
		}
		else {
		    sscanf(word,"%d",&j);
		    printf("\t\t[%f %f %f]\n",
			   GVerts[j-1][0],
			   GVerts[j-1][1],
			   GVerts[j-1][2]);
		}
	    }

	    printf("\t]\n");
	}
    }

    if (GCurrGroupOpen)
        fprintf(stdout,"] /* OBJECT %s */\n", GGroups[GCurrGroup].name);
}

static int strwrd(char * Line)
{
    int i = 1;

    if (!strtok(Line," \t\n"))
        return(0);
    while (strtok(NULL," \t\n") != NULL) 
        i++;

    return i;
}
