#include "../common/structs.h"
#include "./setup_scene.h"
#include "../common/objects.h"
#include "../common/vector.h"
#include "../common/debug.h"
#include "../common/buffer.h"
#include "../shader/shaders.h"
#include "../render/intersect/background.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

extern int DEBUG_LEVEL;

void allocate_buffers()
{
	/* allocated the frame buffers */
	printd(ALERT, "Allocating buffers\n");
    main_scene->frame_buffer = (unsigned char*) malloc(sizeof(unsigned char) *
			main_scene->width * main_scene->height * 3);

    main_scene->back_buffer = (unsigned char*) malloc(sizeof(unsigned char) *
			main_scene->width * main_scene->height * 3);

    main_scene->misc_buffer = (unsigned char*) malloc(sizeof(unsigned char) *
			main_scene->width * main_scene->height * 3);
	
    main_scene->intersect_buffer = (intersect_data*)
		malloc( sizeof(intersect_data) * main_scene->width *
		main_scene->height);
}

void setup_background_object()
{
	if(main_scene->models[0] != NULL)
		return;

	/* set the background color */
	printd(ALERT, "Creating background color\n");
	main_scene->models[0] = make_object(BACKGROUND, 0);
	main_scene->models[0]->shader = (void* (*) (void*, color*)) (&back_black);
	main_scene->models[0]->intersect =  (double (*) (point*, vector*, void*, point*))&intersect_background;
	main_scene->models[0]->normal =  (vector* (*) (point*, void*, vector*))&normal_background;
	make_color(&main_scene->models[0]->amb, 0, 0, 0 );
	make_color(&main_scene->models[0]->diff, 0, 0, 0 );
	make_color(&main_scene->models[0]->spec, 0, 0, 0 );
}

void setup_camera()
{
#define CAMERA1 main_scene->camera
	point* pos = &(CAMERA1->pos);
	point* lookP = &(CAMERA1->lookP);
	vector* look = &(CAMERA1->look);
	vector* up = &(CAMERA1->up);
	vector* horz = &(CAMERA1->horz);
	vector* vert = &(CAMERA1->vert);
	double units = CAMERA1->units;
	double width = main_scene->width;
	double height = main_scene->height;

	/* set up depth stuff */
    units = CAMERA1->units;
    main_scene->stretch_x = units/width/2*(width/height);
    main_scene->stretch_y = units/height/2;
	main_scene->cons_x = width/2*main_scene->stretch_x;
	main_scene->cons_y = height/2*main_scene->stretch_y;

	/* set up needed vectors and points */
	/* normalize the points that we read in */
	normalize( make_vector(lookP, pos, look));   //look vector
	normalize( cross_product(up, look, horz));   //horizontal vector
	invert_vector(horz);
	normalize( cross_product(look, horz, vert)); //vertical vector

	printd(ALERT, "camera values\n");
    printd(ALERT, "  pos=\t%f,\t%f,\t%f\n", pos->x,pos->y,pos->z);
    printd(ALERT, "  lookV=\t%f,\t%f,\t%f\n", look->x,look->y,look->z);
    printd(ALERT, "  up=\t%f,\t%f,\t%f\n", up->x,up->y,up->z);
    printd(ALERT, "  horz=\t%f,\t%f,\t%f\n", horz->x,horz->y,horz->z);
    printd(ALERT, "  vert=\t%f,\t%f,\t%f\n", vert->x,vert->y,vert->z);
}

int setup_scene(scene_data* scene)
{
	allocate_buffers();
	setup_background_object();
	setup_camera();

	printd(ALERT, "render options\n");
    printd(ALERT, "  sub-distance: %i\n", scene->sub_dis);
    printd(ALERT, "  sub-variance: %i\n", scene->sub_var);
    printd(ALERT, "  sub-max level: %i\n", scene->sub_level);
    printd(ALERT, "  max recursions: %i\n", scene->max_recurs);
    printd(ALERT, "  anti-aliasing: %i\n", scene->antialiasing);
    printd(ALERT, "  debug_level: %i\n", DEBUG_LEVEL);

	printd(ALERT, "scene data\n");
	printd(ALERT, "  width: %i, height: %i\n",
			scene->width, scene->height);
	printd(ALERT, "  name: %s, outname: %s\n",
			scene->name, scene->outname);

	return 1;
}
