#ifndef STRUCTS_H
#define STRUCTS_H
#include "../collision/pqp/PQP.h"
#include "../slim.h"
#include "list.h"

#define NUM_OBJECTS 100

/* object types */
#define BACKGROUND 0
#define SPHERE 1
#define PLANE 2
#define DISC 3
#define LIGHT_POINT 4
#define CAMERA 5
#define CYLINDER 6
#define NOTHING 7
#define RECTANGLE 8
#define LIGHT_SPHERE 9
#define LIGHT_SPOT 10
#define LIGHT_INFINITE 11

#define EPSILON 0.001

//char module_path[500];

typedef struct {
	int width;
	int height;
	double *elements;
} dmatrix;

typedef struct
{
	double r;
	double g;
	double b;
} color;

typedef struct
{
	double x;
	double y;
	double z;
} vector;
typedef vector point;  //vectors and points are pretty much the same thing

typedef struct
{
	vector position;
	vector velocity;
	double rot_x;
	double rot_y;
	double rot_z;
} state;

typedef struct
{
	vector *vertices[3];
} triangle;

typedef struct
{
	vector *points;
	triangle *triangles;
	int num_points;
	int num_triangles;
} model;

typedef struct
{
	int id;
	point pos;
	point lookP;
	vector rot;
	vector up;
	vector look;
	vector horz;
	vector vert;
	int units;
} camera_data;
//typedef void (*shader_func)(intersect_data *id, color *new_color);

typedef struct
{
	char no_shadow;
	int obj_type;
	int id;
	point pos;
	vector rot;
	color amb;
	color spec;
	color diff;
	vector up;
	vector norm;
	double spec_alpha;
	double radius;
	double trans;
	double refract;
	double reflect;
	double dist;
	char collided;
	
	double rotation[3][3];

	state st;

	model *polygon;

	//void* shader;
	vector* (*normal) (point* p, void* obj, vector* v);
	double (*intersect) (point* startP, vector* projV,
			void* obj, point* pntIntersect);
	void* (*shader) (void *id, color *new_color);
	void* (*position) (void *id, color *new_color);

	vector* (*inverse_map) (point* p, void* obj, vector* v);

	PQP_Model *pqp_data;
} object;

typedef struct
{
	int obj_num;
	point start;
	point intersect;
	int step;
} int_data;

typedef struct
{
	object* obj;
	point intersect;
	vector proj;
	vector normal;
	vector reflect;
	double distance;
} shading_data;

typedef struct
{
	object* obj;
	point pos;
	int obj_num;
	point start;
	point intersect;
	vector proj;

	vector normal;
	vector reflect;
	//color new_color;
	int step;
	double distance;
} intersect_data;

typedef struct
{
	object* obj;
} buffer_data;


typedef struct
{
	int max_recurs;
	int sub_dis; //distance between sub-samples
	int sub_var; //max variance between colors of samples
	int sub_level; //stop sub-sampling at this level
	int debug_level; //the debug level
	int antialiasing; //aa on or off
	int width;
	int height;
	int num_objects;
	double stretch_x;
	double stretch_y;
	double cons_x;
	double cons_y;
	char name[NAME_LENGTH];
	char outname[NAME_LENGTH];
	char file_content[50000];

	// FIXME: should these be 2 dimensional arrays? might be slower
	unsigned char* frame_buffer;
	unsigned char* back_buffer;
	unsigned char* misc_buffer;
	intersect_data* intersect_buffer;
	//int* obj_buffer;

	object* models[NUM_OBJECTS];
	object* lights[30];
	camera_data* camera;
	object* background;

	/* external modules */
	void* intersect[20];
	void* shader[20];
	void* post_process[20];
	void* render;
	void* pipeline;

	intersect_data intrsct;
} scene_data;

typedef struct
{
	list *options;
	
	void (*set_option) (char *name, void *value);
	void* (*get_option) (char *name);
	
	void (*initialize) (void);
	void (*deinitialize) (void);
	
	void (*render) (int thread_id, int max_num_threads);
} render_engine;

typedef struct
{
	//generic default values
	int max_width;
	int max_height;	
	int default_render;
	int debug_level;

	//buffers
	unsigned char* frame_buffer;
	unsigned char* back_buffer;
	unsigned char* misc_buffer;
	intersect_data* intersect_buffer;

	//threading
	int max_num_threads;
	
	//shaders
	list fragment_shaders;
	list post_shaders;
	list primatives;
	list render_engines;
	
	//active items
	list active_post_shaders;
	render_engine *active_render_engine;
} system_data;

#endif /* STRUCTS_H */





