#include <stdio.h>
#include <string.h> // so far only for memmove
#include <stdlib.h> // exit
#include <math.h>   // sinf, cosf.  Use fixed point later when everything else is working well.
#include <unistd.h> // usleep
#include "edges2faces.h"

static void draw_model_3d(Model *m);
static void reorder_edges(Model *m, int *order, int *reverse);

static int debug = FALSE;
static float angle_rad = 0.0;
static float focal_length = 64.0;

// note: very dependent on the 0,0,0 origin of the model.
//static const int remap_axis[3] = { 0, 1, 2 };    // allow remapping of axes x,y,z (the model itself)
//static const int rotation_axis[3] = { 0, 1, 2 }; // allow remapping of axes x,y,z (the axes the model is rotated around)
//static float object_scale = 1.0;

static int center[3] = {0,0,0}; // during testing, we use this to recenter our single model.

#include "debug.c"
#include "reorder.c"
#include "draw_sdl.c"
#include "write_dot.c"
#include "output_results.c"
#include "edges2faces.c"
#include "three-d.c"

int main(int argc, char **argv) {
  ruid = getuid();
  euid = geteuid();
  Model m;

  // Load a model from:
#include "demo-model.h"
  m.max_edges = DEMO_EDGES;
  m.edge = (Edge *)init_edge;
  m.max_points = DEMO_POINTS;
  m.vertex = (Vertex *)init_vertex;
  m.max_faces = 0; // Demo doesn't come with pre-determined faces.  We generate them internally ourselves.
  m.face = face;
  // (This can be replaced by reading from a file passed via argv.)
  
  // Make sure that there is enough space for the loaded model:
  if (m.max_edges  > MAX_EDGES)  { fprintf(stderr, "edges2faces: please increase MAX_EDGES in edges2faces.h\n");  exit(EXIT_FAILURE); }
  if (m.max_points > MAX_POINTS) { fprintf(stderr, "edges2faces: please increase MAX_POINTS in edges2faces.h\n"); exit(EXIT_FAILURE); }
  if (m.max_faces  > MAX_FACES)  { fprintf(stderr, "edges2faces: please increase MAX_FACES in edges2faces.h\n");  exit(EXIT_FAILURE); }
  
  if (euid == 0) {
    int min[3], max[3];
    for (int i = 0; i < 3; i++) {
      min[i] = m.vertex[0].coord[i]; max[i] = m.vertex[0].coord[i];
    }
    for (vertexidx p = 0; p < m.max_points; p++) {
      for (int i = 0; i < 3; i++) {
        if (m.vertex[p].coord[i] < min[i]) min[i] = m.vertex[p].coord[i];
        if (m.vertex[p].coord[i] > max[i]) max[i] = m.vertex[p].coord[i];
      }
    }
    for (int i = 0; i < 3; i++) center[i] = (max[i]+min[i])/2; // recenter model for rotations.
    fprintf(stderr, "Model between %d,%d,%d and %d,%d,%d: center is %d,%d,%d\n",
            min[0], min[1], min[2],
            max[0], max[1], max[2],
            center[0], center[1], center[2]);
  }

  save_to_graphviz(&m);
  build_nodes(&m); // convert vertexes and separate list of edges into a list of nodes (node = vertex+edges)
  find_faces(&m);
  eliminate_supersets(&m);
  print_results(&m);
  draw_model(&m); // move the draw code to a separate file...

  exit(EXIT_SUCCESS);
  return EXIT_FAILURE;
}
