#include <stdio.h>
#include <stdarg.h>
#include "structs.h"
#include "debug.h"
#include "../slim.h"
#include "../common/buffer.h"

//#define DEBUG_LEVEL 0
extern int DEBUG_LEVEL;

/*
 * INSANE  = 0 = data out  (rays x y, colors, etc)
 * CRAZY   = 1 = section id ('entering diffuse lighting', etc)
 * DEBUG   = 2 = function id ('{entering phong', '}exiting intersect', etc)
 * ALERT   = 3 = non repeated info (assumptions, misc info, etc)
 * MESSAGE = 4 = pipeline id (loading scene, model ids, etc)
 * NORMAL  = 5 = status id (fps, errors, etc)
 * FRAME   = 6 = fps + other data
 * QUIET   = 7 = no output
 */

extern scene_data* main_scene;
extern void (*print_function)(char*, va_list);
extern void (*print_frame_data)(char*, va_list);

INLINE void print_to_stdout(char* msg, va_list args)
{
	vfprintf(stdout, msg, args);
	fflush(stdout);
}

INLINE void printd(int level, char* msg, ...)
{
	va_list args;
	va_start(args, msg);

	if(DEBUG_LEVEL <= 2) //wtf? can't use 'DEBUG'
	{
		fflush(stdout);
		vfprintf(stdout, msg, args);
		fflush(stderr);
	}
	else if (level >= DEBUG_LEVEL)
	{
		if(level == FRAME)
			print_frame_data(msg, args);
		else
			print_function(msg, args);
	}
}

INLINE void print_vector(int level, char* text, vector* v)
{
	printd(level, text);
	printd(level, "%.2f, %.2f, %.2f\n", v->x, v->y, v->z);
}

INLINE void print_color(int level, char* text, color* c)
{
	printd(level, text);
	printd(level, "%.2f, %.2f, %.2f\n", c->r, c->g, c->b);
}


INLINE void print_idata(int level, char *text, intersect_data *i_data)
{

	printd(level, text);
	printd(level, "\n\
\txy: %f,%f\n \
\tstart:%f,%f,%f\n \
\tintersect:%f,%f,%f\n \
\tproj:%f,%f,%f\n \
\tnormal:%f,%f,%f\n \
\treflect:%f,%f,%f\n \
\tstep:%i\n \
\tdistance:%f\n \
\tobj_ptr:%u\n \
\tobj_num:%i\n",
		i_data->pos.x, i_data->pos.y,
		i_data->start.x, i_data->start.y, i_data->start.z,
		i_data->intersect.x, i_data->intersect.y, i_data->intersect.z,
		i_data->proj.x, i_data->proj.y, i_data->proj.z,
		i_data->normal.x, i_data->normal.y, i_data->normal.z,
		i_data->reflect.x, i_data->reflect.y, i_data->reflect.z,
		i_data->step, i_data->distance, i_data->obj, i_data->obj_num);

}


INLINE void print_object(int level, char *text, int m)
{
	#define MODELS main_scene->models
	printd(level, 
"Model[%i], type[%i] - %s\n \
\tpos: %f, %f, %f\n \
\tnormal: %f, %f, %f \
\tradius: %f\n",
		MODELS[m]->id, MODELS[m]->obj_type, text,
		MODELS[m]->pos.x, MODELS[m]->pos.y, MODELS[m]->pos.z,
		MODELS[m]->norm.x, MODELS[m]->norm.y, MODELS[m]->norm.z,
		MODELS[m]->radius);
}

INLINE void print_buffer()
{

	intersect_data* id;
	int i,j;

    for(j=0; j < main_scene->height-main_scene->sub_dis; j++)
    {
        for(i=0; i < main_scene->width-main_scene->sub_dis; i++)
        {
			id = (intersect_data*)get_idata(i,j);
			printd(NORMAL, "%.2f,%.2f,%.2f\t",
					id->normal.x, id->normal.y, id->normal.z);
        }
			printd(NORMAL, "\n");
    }

}

