/*===================================================
=		Função que realiza o exit da par-shell      =
===================================================*/
void exit_par_shell(){
	mutex_lock();
	//	Ativar a flag de exit
	exit_ative = true;
	if(pthread_cond_signal(&podeMonitorizar) != 0){
		perror("Erro no pthread_cond_signal no exit-global da par-shell: ");
	}
	mutex_unlock();

	//	Percorrer os pid's de todos os terminais, terminando-os
	while((pidterminal = remove_terminal(lista_terminais)) > 0){
		kill(pidterminal,SIGKILL);
	}	
	//	Esperar que a tarefa monitora termine
	if(pthread_join(tid,NULL) < 0){
		perror("Erro no pthread_join: ");
		exit(EXIT_FAILURE);
	}
	//	Imprimir lista de informações dos processos filhos executados
	lst_print(list);
	//	Destruir as variáveis e estruturas da par-shell
	destroy_variables();
	//	Sair da par-shell
	exit(EXIT_SUCCESS);	
}
/*////////////////////////////////////////////
/////////////// MAIN FUNCTION ////////////////
////////////////////////////////////////////*/
int main() {
	char* arg[7];
	char buffer[100], filename[100], fnamePipeStats[100];
	int vectorSize = 7, pid, numargs, fd, fDescPIPE, fDescPIPE_S;
	pthread_t waitChild;
	pid_t pidChild;
	terminalLst* terminals = new_terminal_lst();
	l = lst_new();
	if (pthread_mutex_lock(&mutex) != 0) {
		perror(error_mutex_lock);
	}
	if (pthread_mutex_unlock(&mutex) != 0) {
		perror(error_mutex_unlock);
	}
    
	if (pthread_mutex_init(&mutex, NULL) != 0){
		perror(error_mutex);
	}
	if (pthread_cond_init(&can_wait, NULL) != 0) {
		perror(error_cond_init_wait);
	}
	if (pthread_cond_init(&can_execute, NULL) != 0) {
		perror(error_cond_init_execute);
	}
	if (pthread_create(&waitChild, NULL, waitThread, NULL) != 0) {
		perror(error_thread_create);
		exit(EXIT_FAILURE);
	}
    if (signal(SIGINT, CTRLC) == SIG_ERR) {
        perror(error_signal);
    }
	unlink(PIPE); /*-------------------------------------------------*/

	if (mkfifo(PIPE, 0777) != 0) {
		perror(error_mkfifo);
		exit(EXIT_FAILURE);
	}
	if ((fDescPIPE = open(PIPE, O_RDONLY)) == -1) {
		perror(error_pipe_open);
		exit(EXIT_FAILURE);
	}

	close(0);
	dup2(fDescPIPE, 0);

	while (1) {

		numargs = readLineArguments(arg, vectorSize, buffer, 100);

		if(flag_signal)
			break;

		if (numargs <= 1) {
			continue;
		}
		
		if (pthread_mutex_lock(&mutex) != 0) {
			perror(error_mutex_lock);
		}
		while (numChildren == MAXPAR) {
            if (pthread_cond_wait(&can_execute, &mutex) != 0) {
                perror(error_cond_wait);
            }
		}
		if (pthread_mutex_unlock(&mutex) != 0) {
			perror(error_mutex_unlock);
		}
		else if (strcmp(arg[0], EXIT) != 0) {
			if (strcmp(arg[0], starter) == 0) {
				int pid_terminal = atoi(arg[1]);
				insert_terminal(terminals, pid_terminal);
				continue;
			}
			if (strcmp(arg[0], stats) == 0) { /*tratar o PID e meter na lista*/
				sprintf(fnamePipeStats, "%s-%s", PIPE_S, arg[1]);
                
                while((fDescPIPE_S = open(fnamePipeStats, O_WRONLY)) < 0);
                if(fDescPIPE < 0) {
					perror(error_pipe_open);
					exit(EXIT_FAILURE);
				}
				if (pthread_mutex_lock(&mutex) != 0) {
                    perror(error_mutex_lock);
                }

				sprintf (buffer, "Number of active children: %d\nTotal execution time to the moment: %d", numChildren, timeTotal);
				write(fDescPIPE_S, buffer, strlen(buffer));
                if (pthread_mutex_unlock(&mutex) != 0) {
                    perror(error_mutex_unlock);
                }

				close(fDescPIPE_S);
				continue;
			}

            if (strcmp(arg[0], EXITGLOBAL) == 0) { /* SONFOILULDNILDEFNC*/
                printf("1\n");
                CTRLC(SIGINT);
            }
			else {
				pid = fork();
				if (pid < 0) {
					perror(error_fork);
				}
				if (pthread_mutex_lock(&mutex) != 0) {
					perror(error_mutex_lock);
				}
				insert_new_process(l, pid, time(NULL));
				numChildren++;
				if (pthread_cond_signal(&can_wait) != 0) {
					perror(error_cond_wait);
				}
				if (pthread_mutex_unlock(&mutex) != 0) {
					perror(error_mutex_unlock);
				}
				if (pid == 0) {
					pidChild = getpid();
					sprintf(filename, "par-shell-%d.txt", pidChild);
					fd = open(filename,  O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
					close(1);
					dup(fd);
					close(fd);
					if (execv(arg[0], arg) < 0) {
						perror(error_execv);
						exit(EXIT_FAILURE);
					}
				}
				else {
					sprintf(filename, "par-shell-%d.txt", pid);
				}
			}
        }
        else {
            break;
        }
	}
	isExit = true;
    if (pthread_cond_signal(&can_wait) != 0) {
        perror(error_cond_wait);
    }
    if (pthread_mutex_unlock(&mutex) != 0) {
        perror(error_mutex_unlock);
    }
    if (pthread_join(waitChild, NULL) != 0) {
        perror(error_thread_join);
    }
    lst_print(l);
    lst_destroy(l);
    while(remove_terminal(terminals)!= -1){

    }
    if (pthread_cond_destroy(&can_wait) != 0) {
        perror(error_cond_destroy_wait);
    }
    if (pthread_cond_destroy(&can_execute) != 0) {
        perror(error_cond_destroy_execute);
    }
    exit(EXIT_SUCCESS);
	return 0;
}