#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include "Common.h"
#include "Integrated.h"
#include "Pish.h"

// Main function for Pish program
void Pish(void)
{
    CommandStruct commandParentObject = {"", 0};
    CommandStruct commandChildObject = {"", 0};
    CommandStruct* commandParent = &commandParentObject;
    CommandStruct* commandChild = &commandChildObject;
    char inputString[1000]; // Max 1000 characters
    int forkPID;
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
    ReadPishrc(commandParent, commandChild, inputString);
    while (1)
    {
        int pipefd[2];
        ResetCommandStruct(commandParent); // Clean command
        strcpy(inputString, "");    // Clean inputString
        GetInput(inputString);
		if (strcmp(inputString, "") == 0)
			continue;
        SplitInput(inputString, commandParent);
        if (IntegratedCheck(commandParent))
            continue;
        forkPID = ExecPipe(commandParent, commandChild, pipefd);
        // CheckRedirection(inputString, command);
        // CheckRedirection(command);
        // ioRedirection(command);
        // Child
        if (forkPID == 0)
            RunChild(commandChild, pipefd);
        // Parent
        // This is the parent process; Wait for the child to finish
    }
}

// Reads ~/.pishrc and runs each command in the file
void ReadPishrc(CommandStruct *commandParent, CommandStruct *commandChild, char *inputString)
{
	char buffer[1];
	int pipefd[2];
	int forkPID;
	int *argc = &(commandParent->argc);
	char* pishLocation = GetHomeDir();
	strcat(pishLocation, "/.pishrc");
	int fd = open(pishLocation, O_RDONLY | O_CREAT, 0644);
	assert(fd > -1);
	while (read(fd, buffer, 1) > 0)
	{
		if (buffer[0] == '\n')
		{
		  	SplitInput(inputString, commandParent);
			if (IntegratedCheck(commandParent))
				continue;
			forkPID = ExecPipe(commandParent, commandChild, pipefd);
			if (forkPID == 0)
				RunChild(commandChild, pipefd);
			strcpy(inputString, "");
			ResetCommandStruct(commandParent);
			continue;
		}
		strcat(inputString, buffer);
	}
	assert(close(fd) >= 0);
}

// Run a child process
void RunChild(CommandStruct* commandChild, int* pipefd)
{
	close(pipefd[0]);
	dup2(pipefd[1], 1);
	close(pipefd[1]);
	// execve() is recommended, execvpe() may be better
	CheckRedirection(commandChild);
	// ioRedirection(commandChild);
	execvp(commandChild->argv[0], commandChild->argv);
	// exec does not return if it succeeds
	printf("ERROR: Could not execute %s\n", commandChild->argv[0]);
	exit(1);
}