// queue
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include "glob.h"
#include <string.h>

int qsize;
int totalb=0;
int q=2;
char s[50],s1[50];
struct dirent *dd;
DIR *d;

volatile int changed=0;
volatile int sig4=0;
volatile int sig3=0;
volatile int sig6=0;
volatile int sig7=0;

int fileexist=0;

void sig4h(int s)
{
	sig4=1;
	changed=1;
}
void sig3h(int s)
{
	sig3=1;
	changed=1;
}
void sig6h(int s)
{
	sig6=1;
	changed=1;
}
void sig7h(int s)
{
	sig7=1;
	changed=1;
}

void callbaker(void)
{
	d=opendir("./tmp");
	while((dd=readdir(d))!=0) if(dd->d_name[0]=='r')
	{
		int h;
		pid_t bid;
		sprintf(s, "./tmp/%s",dd->d_name);
		unlink(s);
		sscanf(dd->d_name,"r%d",&h);
		bid=h;
		kill(bid,SIG1);
	}
	closedir(d);	
}

void moveloafs(void)
{
	d=opendir("./in");
	while((totalb<qsize) && (dd=readdir(d))!=0) if(dd->d_name[0]!='.')
	{
		int h;
		pid_t bid;
		sprintf(s,  "./in/%s",dd->d_name);
		sprintf(s1, "./out/%d",q++);
		rename(s,s1);
		sscanf(dd->d_name,"%d",&h);
		bid=h;
		kill(bid,SIG2);
		totalb++;
	}
	closedir(d);
}

void renameloaf(void)
{
	d=opendir("./out");
	int h,minh=2000000000;
	char good[50];
	while((dd=readdir(d))!=0) if(dd->d_name[0]!='.')
	{
		sscanf(dd->d_name,"%d",&h);
		if(h<minh)
		{
			minh=h;
			strcpy(good,dd->d_name);
		}
	}
	if(minh!=2000000000)
	{
		sprintf(s,"./out/%s",good);
		rename(s,"./out/1");
		fileexist=1;
	} else {
		fileexist=0;
	}
	closedir(d);

}


void giveloaf(void)
{
DIR *d;
	if(!fileexist && totalb>0)
	{
		d=opendir("./tmp");
		while((dd=readdir(d))!=0) if(dd->d_name[0]=='h')
		{
			int h;
			pid_t cid;
			sprintf(s, "./tmp/%s",dd->d_name);
			unlink(s);
			sscanf(dd->d_name,"h%d",&h);
			cid=h;
			renameloaf();
			sprintf(s,"./tmp/e%d",h);
			FILE* f=fopen(s,"w");
			fclose(f);
			//printf("Q Giving loaf to Customer %d.\n",(int)cid);
			fflush(stdout);
			kill(cid,SIG5);
			totalb--;
			break;
		}
		closedir(d);
	}
}

void deleteefile(void)
{
	d=opendir("./tmp");
	while((dd=readdir(d))!=0) if(dd->d_name[0]=='e')
	{
		sprintf(s, "./tmp/%s",dd->d_name);
		unlink(s);
		break;
	}
	closedir(d);
}


int main(int argc, char** argv) // path, qsize
{
	//int i;

	// params
	sscanf(argv[1], "%d", &qsize);

	// signals
	sigset_t ss;
	sigemptyset(&ss);
	sigaddset(&ss, SIG4);
	sigaddset(&ss, SIG3);
	sigaddset(&ss, SIG6);
	sigaddset(&ss, SIG7);
	sigprocmask(SIG_BLOCK, &ss, 0);
	sigemptyset(&ss);
	
	// handlers
	signal(SIG4, sig4h);
	signal(SIG3, sig3h);
	signal(SIG6, sig6h);
	signal(SIG7, sig7h);

	
	//cycle
	while(1)
	{
		sig4=0;
		sig3=0;
		sig6=0;
		sig7=0;
		changed=0;
		//printf("Q Waiting...\n");
		while(!changed)
			sigsuspend(&ss);
	
		if(sig4)
		{
			//printf("Q SIG4 Received\n");
			callbaker();
		}

		if(sig3)
		{
			//printf("Q SIG3 Received\n");
			moveloafs();
			giveloaf();
		}

		if(sig6)
		{
			//printf("Q SIG6 Received\n");
			giveloaf();
		}

		if(sig7)
		{
			//printf("Q SIG7 Received\n");
			fileexist=0;
			deleteefile();
			moveloafs();
			giveloaf();
		}
			
	}
	
	return 0;
}

