/**
 * Blurs an image.
 * @author Nicolas 'Nerpson' Jullien
 * @version 2018-01-16
 */

#include <pthread.h>
#include "image.h"

#define MODE_ROW	0
#define MODE_COLUMN	1

typedef struct thread_params
{
	struct image * in;
	struct image * out;
	size_t radius;

	unsigned short mode;
	size_t part;

} thread_params_t;

void * thread_blur_part(void * param)
{
	thread_params_t * thread_param = (thread_params_t *) param;

	// Chooses the correct function according to the given mode.
	if (thread_param->mode == MODE_ROW)
	{
		blur_image_row(thread_param->in, thread_param->out, thread_param->radius, thread_param->part);
	}
	else
	{
		blur_image_column(thread_param->in, thread_param->out, thread_param->radius, thread_param->part);
	}
	
	return NULL;
}

int main(int argc, char **args)
{

	if (argc == 4)
	{

		size_t radius = strtoul(args[3], 0, 0);

		unsigned short selected_mode;
		unsigned i;
		size_t parts_count;

		// Loads the input image and creates an output image.
		struct image input	= make_image_from_file(args[1]);
		struct image output	= make_image(input.type, input.row_count, input.column_count, input.max_value);

		// Selects the most relevant way to split the image.
		if (input.row_count > input.column_count)
		{
			selected_mode	= MODE_ROW;
			parts_count		= input.row_count;
		}
		else
		{
			selected_mode	= MODE_COLUMN;
			parts_count		= input.column_count;
		}

		// Allocates memory for the threads.
		pthread_t * threads = malloc(sizeof(pthread_t) * parts_count);

		// Initializes the different parameters that will be passed in each thread.
		thread_params_t * params = malloc(sizeof(thread_params_t) * parts_count);
		for (i = 0; i < parts_count; ++i)
		{
			params[i].in		= &input;
			params[i].out		= &output;
			params[i].radius	= radius;
			params[i].mode		= selected_mode;
			params[i].part		= i;
		}

		// Starts the threads.
		for (i = 0; i < parts_count; ++i)
		{
			pthread_create(&threads[i], 0, thread_blur_part, (void *) &params[i]);
		}

		// Waits for them to end their tasks.
		for (i = 0; i < parts_count; ++i)
		{
			pthread_join(threads[i], NULL);
		}

		write_image_to_file(&output, args[2]);

		// Frees the memory used by the threads.
		free(threads);
		free(params);

	}
	else
	{
		fprintf(stderr, "Essaie plutÃ´t : %s input.ppm output.ppm 10\n", args[0]);
	}
}
