#ifndef _TYPES_H_
#define _TYPES_H_ 1

#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif

// These limits are upper limits and are currently used to declare some
// static arrays for storing temporary data in.  Ideally this space would
// come off the heap, and indeed my 'flex array' package would be a better
// fit although it's a lot more code and frankly it's easy enough to just
// bump up these constants should we hit a limit...
#define MAX_POINTS 21
#define MAX_NODES MAX_POINTS
#define MAX_FACES (MAX_POINTS*1024*16)
#define MAX_QUEUE 1024
#define MAX_EDGES 35

int order[MAX_EDGES];
int reverse[MAX_EDGES];
int used[MAX_EDGES];

typedef struct {
  int x, y;
} Vectrex_Screen_Coordinate;
Vectrex_Screen_Coordinate screen[MAX_POINTS];


// A coordinate in world space.  We're using ints for now.  Might switch to floating point.
typedef int32_t coord;


typedef struct {
  coord coord[3]; // X, Y, Z
  u_int8_t az; // Azimuth and Elevation - angles from 0. 256 angles in a circle.
               // Azimuth is horizontal plan, Elevation is vertical plane.
  u_int8_t el; // Coordinates are relative to center of model determined from cartesian coordinates.
} Vertex;
typedef int vertexidx;


typedef struct {
  vertexidx from;
  vertexidx to;
} Edge;
typedef int edgeidx;


typedef struct {
  edgeidx   edge_count;
  edgeidx   edge[MAX_POINTS];
  vertexidx this_vertex;
} Node;
typedef edgeidx nodeidx;
static Node node[MAX_NODES];


// Used for orienting the model:
typedef struct {
  float m[4][4];
} Matrix4x4;


typedef struct {
  float scale;           // Tweak model size by constant scale factor.
                         // (Could be stored in rotation matrix instead)
  Matrix4x4 orientation; // Object's orientation.

  // I have however been contemplating using polar coordinates for models, which would
  // consist of azimuth and elevation which would define a direction vector, along with
  // a rotation for the object around that direction vector.  Later...
  
  vertexidx origin;      // Point around which the model might be rotated.  Also zero reference for polar coordinates.
  vertexidx max_points;
  Vertex   *vertex;      // Unique list of x,y,z points used for the model,
                         // and also the model's origin.

  edgeidx max_edges;
  Edge *edge;            // List of edges comprising the model

} Model;


typedef struct {
  // for now the camera is just an x,y,z position and focal length.
  // but it could potentially include a direction and rotation.
  // For now it is looking straight ahead and it's up to the game
  // to ensure the action occurs in front of the camera.  Battlezone
  // would require a camera that could point in all 360 degrees.
  Vertex origin;
  int    focal_length;
} Camera;


typedef struct {
  int xl, yb, xr, yt;    // vectrex display is -128:127 on both axes
                         // but because of aspect-ratio we may need to
                         // add some tweaks.
} Window;


typedef struct {
  Window *view;          // coordinate range of display screen.
  Model  *model;         // array of objects to be viewed
  Camera *camera;        // viewing position
} World;

#endif // _TYPES_H_
