#define	LIBQTOOLS_CORE
#include "../include/libqtools.h"

/* trilib.c: library for loading triangles from an Alias triangle file */

static struct triangle {
  struct aliaspoint pt[3];
};

static void ByteSwapTri(struct triangle *tri)
{
  int i;

  for (i = 0; i < sizeof(struct triangle) / 4; i++) {
    ((int *)tri)[i] = BigLong(((int *)tri)[i]);
  }
}

bool LoadTriangleList(__memBase, char *fileName)
{
  HANDLE input;
  float start;
  char name[NAMEPATH_LEN], tex[256];
  int i, count, magic;
  struct triangle tri;
  struct triangle *ptri;
  int iLevel;
  int exitpattern;
  float t;
  bool success;

  t = -FLOAT_START;
  *((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
  *((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
  *((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
  *((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);

  if ((input = __open(fileName, H_READ_BINARY))) {
    iLevel = 0;

    __read(input, &magic, sizeof(int));

    if (magic == BigLong(MAGIC_TRI)) {
      AllocClusters(bspMem, TRIANGLES);
      ptri = bspMem->triangles;

      while (__read(input, &start, sizeof(float))) {
	*(int *)&start = BigLong(*(int *)&start);

	if (*(int *)&start != exitpattern) {
	  if (start == FLOAT_START) {
	    /* Start of an object or group of objects. */
	    i = -1;
	    do {
	      /*
	       * There are probably better ways to read a string from 
	       * a file, but this does allow you to do error checking 
	       * (which I'm not doing) on a per character basis.      
	       */
	      ++i;
	      __read(input, &(name[i]), sizeof(char));
	    } while (name[i] != '\0');

	    __read(input, &count, sizeof(int));

	    count = BigLong(count);
	    ++iLevel;
	    if (count != 0) {
	      i = -1;
	      do {
		++i;
		__read(input, &(tex[i]), sizeof(char));
	      } while (tex[i] != '\0');
	    }
	    /*
	     * Else (count == 0) this is the start of a group, and 
	     * no texture name is present. 
	     */
	  }
	  else if (start == FLOAT_END) {
	    /*
	     * End of an object or group. Yes, the name should be 
	     * obvious from context, but it is in here just to be 
	     * safe and to provide a little extra information for 
	     * those who do not wish to write a recursive reader. 
	     * Mia culpa. 
	     */
	    --iLevel;
	    i = -1;
	    do {
	      ++i;
	      __read(input, &(name[i]), sizeof(char));
	    } while (name[i] != '\0');
	    continue;
	  }
	}

	/*
	 * read the triangles
	 */
	for (i = 0; i < count; ++i) {
	  int j;

	  __read(input, &tri, sizeof(struct triangle));

	  ByteSwapTri(&tri);
	  for (j = 0; j < 3; j++) {
	    int k;

	    for (k = 0; k < 3; k++) {
	      ptri->verts[j][k] = tri.pt[j].p.v[k];
	    }
	  }

	  if (bspMem->numtriangles == bspMem->max_numtriangles)
	    ExpandClusters(bspMem, TRIANGLES);
	  bspMem->numtriangles++;
	  ptri = bspMem->triangles + bspMem->numtriangles;
	}
      }

      __close(input);
      success = TRUE;
    }
    else
      eprintf("file %s is not a Alias object separated triangle file, magic number is wrong.\n", fileName);
  }
  else
    eprintf(failed_fileopen, fileName);

  return success;
}
