#ifndef _JRN_GRAPH_H
#define _JRN_GRAPH_H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include "labellist.h"
#include "globals.h"
#include "vcbbtree.h"

//layout_graph delay
#ifdef _WIN32
	#include <windows.h>
#else
	#include <unistd.h>
#endif

#ifndef M_PI
	#define  M_PI   3.14159265358979323846f 
#endif
#define               true        ((boolean) 1)
#define               false       ((boolean) 0)
#define MIN(x,y)  ((x)<(y)?(x):(y))
#define MAX(x,y)  ((x)>(y)?(x):(y))
#define ABS(x)    ((x)<0?-(x):(x))
#define SIGN(x)   ((x)<0?-1:1)
#define SQR(x)    ((x)*(x))
#define NORMSQR(v)    ((SQR(v.x))+(SQR(v.y))+(SQR(v.z)))
#define NORM(v)       (sqrt(1.0*(NORMSQR(v))))
#define SKALPROD(v,w) ((v.x)*(w.x)+(v.y)*(w.y)+(v.z)*(w.z))
#define COS(v,w)      ((SKALPROD ((v),(w))*1.0) / (sqrt (1.0 * NORMSQR(v) * NORMSQR(w))))
#define ANGLE(v,w)    (acos (1.0* (COS((v),(w)))))
#define RotXY(i,j)   (SIGN (((i.x)*(j.y)) - ((i.y)*(j.x))))
#define RotYZ(i,j)   (SIGN (((i.y)*(j.z)) - ((i.z)*(j.y))))
#define RotXZ(i,j)   (SIGN (((i.x)*(j.z)) - ((i.z)*(j.x))))

#define for_all_vertices(data,vert)   for (vert=1; vert<=data->numVerts; vert++)
#define for_all_edges(data,ed)        for (ed=1; ed<=data->numEdges; ed ++)
#define vertexCount(data)             data->numVerts
#define edgeCount(data)               data->numEdges
#define get_vertex(data,vert)         data->vi[vert]
#define mod_vertex(data,vert)         data->vi+vert
#define this_vertex(data,ed)          data->VERTEX[ ed]
#define that_vertex(data,ed)          data->VERTEX[-ed]

typedef char* string;
typedef short int vertex;
typedef short int edge;
typedef struct {
  long int x, y, z;
}   vector;

typedef struct {
  string name;
  vector size;
  int    weight;
  vector pos;
  vector imp;
  float  heat;
  float  dir1;
  float  dir2;
  float  dir3;
  int    form;
  int    farbe;
}  vertexinfo;

typedef struct {
  float ao;		//Oscillation
  float ar;		//Rotation
  float so;		//Oscillation Reaction Intensity
  float sr;		//Rotation Reaction Intensity
  float grav;
  int rd;
  int termAbs;
  int termPer;
  int springAlgo;
  //For file output
  float thresh;
  int absValFlag;
  int attractFlag;
} parameter;

typedef struct {
  string  name;			//Name of graph
  int numVerts;			//Total number of vertices
  int numEdges;			//Total number of edges
  short int** mat2d;	   //Edge weights in LTM format
  LabelList* edgeLabels;//Binary tree of edge labels for searching
  int** degree;			//Degree of each vertex for each threshold
  vertex *VERTEX;		   //Vertex pointer of short ints
  vertexinfo* vi;		   //Vertex information initially used for layout
  int numExistentEdges; //Current number of edges for layout

  VCB_mntree vertRoot;	//Root of tree for vertex queries
  int numVertFeatures;	//Number of features to query on
  float* vertData;		//Data used for querying
  int vertLabelAlias;   //Use different names for display verts?
  char** vertLabels;    //Alias names

  VCB_mntree edgeRoot;	//Tree for querying edge data (not currently used)
  int numEdgeFeatures;
  float* edgeData;

  int numQueries;		   //Number of concurrent queries
  int* queryColors;		//Color index to assign vertices for each query
  float** fltQuery;		//Query in floating point array (execution)
  char** strQuery;		//Query as string (display)

  int*  numBin;         //Number of vertices in each bin
  int** lodBin;         //List of original vertices comprising each LOD vert

  //Display information
  float scale[3];		   //Scale the entire graph
  short int offset[3];  //Offset the entire graph
  int numDisplayVerts;	//Number of vertices currently being displayed
  int* vertList;		   //List of vertex indices to display
  int* vertColorList;	//Index to color each vertex
  short int* vertPosn;  //Display position for each vertex
  int haloColorIdx;     //Color index of the splat background  

  int numDisplayEdges;	   //Number of edges to display
  unsigned short* edgeList;//List of edges to display
  int* edgeList1d;		   //Same data as edgeList
  unsigned short* tl1d2;   //Conversion from 1d to 2d lookup
} graph;

#ifdef __cplusplus
extern "C" {
#endif

graph* init_graph (string name, int n_vert, int n_edge, short int** mat2d, LabelList* edgeLabels);
parameter* init_param_default();
parameter* init_param(float ao, float ar, float so, float sr, float grav, int rd, int termAbs, int termPer);

void layout_graph_main (graph* data, parameter* p, int delay, int iterations);
void layout_graph_iterations (graph* data, parameter* p, int iterations);
void layout_graph_delay (graph* data, parameter* p, int delay);
void layout_graph (graph* data, parameter* p);

void set_export_each_timestep(int exportBool);

//Get current position of vertices in floating point (internally stored as ints)
void get_layout (graph* data, parameter* p, int* numVerts, float** vertLocs);

//File format:
// filename thresh absValFlag attractFlag gravity springEmbedAlgo#
// numVerts numEdges
// vertName x y z\n....
void write_layout(char* filename, graph* data, parameter* p);

void write_graph(char* filename, graph* data, string format);
void read_graph(char* filename, graph* data, string format);

#ifdef __cplusplus
}
#endif

#endif
