#include "../../common/buffer.h"
#include "../../common/colors.h"
#include "../../common/debug.h"
#include "../shaders.h"
#include "../../parse/parser.h"
#include <stdlib.h>
#include <string.h>

typedef struct {
	int threshold;
	double amount;
//	void *cdata;
	shader_data conv;
} bloom_data;

int _init_bloom(void **data_ptr, char *input)
{
	bloom_data *data;
	shader_data *conv;
	
	conv = get_shader("convolve");

	if(conv == NULL)
	{
		printd(NORMAL, "bloom needs convolve shader to work\nnow exploding\n");
		exit(1);
	}

	data = (bloom_data*)malloc(sizeof(bloom_data));
	
	data->conv.run = conv->run;
	data->conv.init = conv->init;
	data->conv.cleanup = conv->cleanup;
	data->conv.help_text = conv->help_text;
	data->conv.name = conv->name;

	if(data->conv.init(&data->conv.data, input) == 0)
	{
		goto error;
	}

//	data->conv.data = data->conv.init(input);
	//void *cdata = data->conv.init(input);
//	data->cdata = cdata;

	//assuming convolve has already started tokenizing...
	//FIXME: ^ terrible. fix it.
	if(assign_int(&data->threshold, strtok(NULL, ",")) == 0)
		goto error;

	if(assign_double(&data->amount, strtok(NULL, ",")) == 0)
		goto error;

	*data_ptr = (void*)data;
	return 1;

error:
	free(data);
	return 0;
}


//gets brights from fb, stores brights in mb
//blurs mb, stores in bb
//combines fb and mb into bb
void _run_bloom(bloom_data *data)
{
	unsigned char *fb, *bb, *mb;
	int i,j;
	color old_color;
	color new_color;
	int bright_threshold;
	double bloom_amount;
	
	bright_threshold = data->threshold;
	bloom_amount = data->amount;

//	double m[125] = {1,4,6,4,1,4,4,16,24,16,4,6,24,36,24,6,4,16,24,16,4,1,4,6,4,1};
	fb = main_scene->frame_buffer;
	bb = main_scene->back_buffer;
	mb = main_scene->misc_buffer;

	//set the misc buffer to the bright areas
	for(j=0; j<main_scene->height; j++)
	{
		for(i=0; i<main_scene->width; i++)
		{
			main_scene->frame_buffer = fb;
			get_color(i, j, &new_color);

			main_scene->frame_buffer = mb;
			if(new_color.r > bright_threshold ||
					new_color.g > bright_threshold ||
					new_color.b > bright_threshold)
			{
				set_color(i, j, &new_color);
			}
			else
			{
				clear_color(&new_color);
				set_color(i, j, &new_color);
			}
		}
	}

	main_scene->frame_buffer = mb;
	data->conv.run(data->conv.data);


	//add in the new blurred image
	for(j=0; j<main_scene->height; j++)
	{
		for(i=0; i<main_scene->width; i++)
		{
			main_scene->frame_buffer = fb;
			get_color(i, j, &new_color);
			main_scene->frame_buffer = bb;
			get_color(i, j, &old_color);
			multiply_color(&old_color, bloom_amount);
			add_colors(&new_color, &old_color);

			main_scene->frame_buffer = fb;
			set_color(i, j, &new_color);
		}
	}
	main_scene->frame_buffer = fb;
	main_scene->back_buffer = bb;
	main_scene->misc_buffer = mb;
}


void _cleanup_bloom(void* data)
{
	bloom_data *bdata;
	bdata = (bloom_data*)data;
	bdata->conv.cleanup(bdata->conv.data);
	free(bdata);
}

shader_data bloom =
{
	"bloom",
	"options:\n   bloom <matrix convolve> <int threshold> <double alpha>\n",
	(int (*)(void*, char*))_init_bloom,
	(void* (*)(void*))_run_bloom,
	(void* (*)(void*))_cleanup_bloom,
};

shader_data* get_bloom()
{
	return &bloom;
}





