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

int _init_convolve(void **data_ptr, char *input)
{
	dmatrix *matrix = (dmatrix*) malloc(sizeof(dmatrix));
	if(assign_dmatrix(matrix, input) == 0)
	{
		free(matrix);
		return 0;
	}

	*data_ptr = (void*)matrix;
	return 1;
}

void _run_convolve(void *data)
{
	int i, j, x, y;
	color blur_color, temp_color;
	unsigned char *fb, *bb;
	double scale = 0;
	int horz;

	int width;
	int height;
	double *elements;
	dmatrix *conv;

	conv = (dmatrix*)data;
	width = conv->width;
	height = conv->height;
	elements = conv->elements;
	horz = (width - 1) / 2;

	for(i=0; i<width*height; i++)
			scale += elements[i];
	if(scale < 1)
		scale = 1;
	else
		scale = 1/scale;

	fb = main_scene->frame_buffer;
	bb = main_scene->back_buffer;

	for(y = 0; y < main_scene->height - height; y++)
	{
		for(x = horz+1; x < main_scene->width - width; x++)
		{
			//apply the convolution matrix
			main_scene->frame_buffer = fb;
			for(j=0; j < height; j++)
			{
				for(i=0; i < width; i++)
				{
					get_color(x+i, y+j, &temp_color);
					multiply_color(&temp_color, elements[j*height+i]);
					add_colors(&blur_color, &temp_color);
				}
			}

			//normalize
			multiply_color(&blur_color, scale);

			main_scene->frame_buffer = bb;
			set_color(x+width, y+height, &blur_color);
			clear_color(&blur_color);
		}
	}
 
	main_scene->frame_buffer = bb;
	main_scene->back_buffer = fb;
}


void _cleanup_convolve(void* data)
{
	free(((dmatrix*)data)->elements);
	free((dmatrix*)data);
}


shader_data convolve =
{
	"convolve",
	"options:\n   convolve <matrix convolution>\n",
	(int (*)(void*, char*))_init_convolve,
	(void* (*)(void*))_run_convolve,
	(void* (*)(void*))_cleanup_convolve,
};

shader_data* get_convolve()
{
	return &convolve;
}

