#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>

typedef struct {
	int initialWidth;
	int initialHeight;
	int finalWidth;
	int finalHeight;
	pthread_mutex_t rightMutex;
	pthread_mutex_t leftMutex;
	pthread_mutex_t upMutex;
	pthread_mutex_t downMutex;
	pthread_mutex_t downRightMutex;
	pthread_mutex_t upRightMutex;
	pthread_mutex_t upLeftMutex;
	pthread_mutex_t downLeftMutex;
	short leftReady;
	short rightReady;
	short upReady;
	short downReady;
	short upRightReady;
	short upLeftReady;
	short downRightReady;
	short downLeftReady;
	pthread_cond_t leftCondition;
	pthread_cond_t rightCondition;
	pthread_cond_t upCondition;
	pthread_cond_t downCondition;
	pthread_cond_t upLeftCondition;
	pthread_cond_t upRightCondition;
	pthread_cond_t downLeftCondition;
	pthread_cond_t downRightCondition;
	threadParametersType *leftThreadParameters;
	threadParametersType *rightThreadParameters;
	threadParametersType *upThreadParameters;
	threadParametersType *downThreadParameters;
	threadParametersType *upLeftThreadParameters;
	threadParametersType *upRightThreadParameters;
	threadParametersType *downLeftThreadParameters;
	threadParametersType *downRightThreadParameters;
}threadParametersType;


void doDirtyWork(void *arg);
void splitWork(int numberOfThreads, short division, int imageWidth, int imageHeight);

int **imageMatrix;
threadParametersType *parameters;

int main(int argc, char **argv){
	char inputFile[200], outputFile[200];
	int numberOfThreads, numberOfDesiredThreads;
	int imageWidth, imageHeight;
	short ajusted, division;

	if (argc != 4){
		fprintf(stderr, "Invalid output!\n");
		usage();
		return -1;
	}
	
	numberOfDesiredThreads = atoi(argv[1]);
	inputFile = argv[2];
	outputFile = argv[3];

	readFileAndPrepareData(inputFile);
	
	ajusted = 0;
	division = 0;
	while(!ajusted){
		if ((division+1)*(division+1)>numberOfDesiredThreads){
			division--;
			ajusted = 1;
		}else{
			division++;
		}
	}
	
	numberOfThreads = division*division;

	printf("Number of threads beeing created: %d \n",numberOfThreads);
		
	splitWork(numberOfThreads, division, imageWidth, imageHeight);
	
	writeDataToFile(outputFile);
	return 0;
}

void usage(){
	prinf("Usage:\n\tthinning <number of threads desired> <input file> <output file>");
}

void doDirtyWork(void *arg){

	
}

void splitWork(int numberOfThreads, short division, int imageWidth, int imageHeight){
	int i, parts, atualXPart, atualYPart;
	int xInitial, yInitial, xFinal, yFinal;
	int pixelsPerXDivision, pixelsPerYDivision;
	
	pixelsPerXDivision = floor((double)imageWidth/(double)parts);
	pixelsPerYDivision = floor((double)imageHeight/(double)parts);

	parameters = (*threadParametersType) malloc(numberOfThreads*sizeof(threadParametersType));

	parts = division + 1;
	for(atualYPart=0;atualYPart<parts;atualYPart++){
		
		for(atualXPart=0;atualXPart<parts;atualXPart++){
			
			xInitial = pixelsPerXDivision*atualXPart;
			
			if (atualXPart==(parts-1)) //the last one
				xFinal = imageWidth-1;
			else
				xFinal = xInitial+pixelsPerXDivision;
		}
		
		yInitial = pixelsPerYDivision*atualYPart;
		
		if (atualYPart==(parts-1))//the last one
			yFinal = imageHeight-1;
		else
			yFinal = yInitial+pixelsPerYDivision;

		parameters[atualXPart+atualYPart].initialWidth = xInitial;
		parameters[atualXPart+atualYPart].initialHeight = yInitial;
		parameters[atualXPart+atualYPart].finalWidth = xFinal;
		parameters[atualXPart+atualYPart].finalHeight = yFinal;

	}
}

