#include <assert.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Integrated.h"

// Gets home directory location of user
const char *GetHomeDir(void)
{
	char *homeDir = (getpwuid(getuid()))->pw_dir;
	strcat(homeDir, "/.pishrc");
	return homeDir;
}

// Checks for commands that are built into Pish
void IntegratedCheck(CommandStruct *command)
{
	if (strcmp(command->argv[0], "exit") == 0)
		exit(0);
	// If there is an argument, change to argument location
	// Else, change to home directory
	if (command->argv[0][0] == 'c' && command->argv[0][1] == 'd')
		;
	return;
}

// Prints a prompt and then reads a command from the terminal
void GetInput(char *inputString)
{
	char c;
	char *prompt = "pish%>";
	printf("%s ", prompt);
	// assert(scanf("%[^\n]s", inputString) == 1);
	scanf("%1000[^\n]s", inputString);
	while ((c = getchar()) != '\n' && c != EOF)
		/* discard */;
	return;
}

// Splits a string separated by spaces into an array of strings
void ParseInput(char *inputString, CommandStruct *command)
{
	// Parse command
	int *argc = &(command->argc);
	char *token = strtok(inputString, " ");
	command->argv[*argc] = token;
	(*argc)++;
	while (token != NULL)
	{
		// This only holds 1 command at a time then it overrides
		// Will need modified
		token = strtok(NULL, " ");
		command->argv[*argc] = token;
		(*argc)++;
	}
}

// Reads ~/.pishrc and runs each command in the file
void ReadPishrc(CommandStruct *command, char *inputString)
{
	char buffer[1];
	int forkID;
	int *argc = &(command->argc);
	int fd = open(GetHomeDir(), O_RDONLY | O_CREAT);
	assert(fd > -1);
	while (read(fd, buffer, 1) > 0)
	{
		if (buffer[0] == '\n')
		{
			ParseInput(inputString, command);
			forkID = fork();
			if (forkID == 0)
				execvp(command->argv[0], command->argv);
			else
				wait(&forkID);
			strcpy(inputString, "");
			ResetCommandStruct(command);
			continue;
		}
		strcat(inputString, buffer);
	}
	assert(close(fd) >= 0);
}

// i/o redirection
// TODO: Work on one symbol at a time
// 		 inputString may not be useful here, only *command
// 		 Try to add a layer of abstraction where possible
// 		 I.E. think about using function instead for checking
void ioRedirection(CommandStruct *command)
{
	int newfd;
	// check command standard output
	// TODO: Check command->argv[] for symbol instead
	for(int i = 0; i < sizeof(command); i++)
	{  
	  if (strchr(command->argv[i], '>') != NULL)
	  {
	    output(command->argv[i+1]); 
    	// 		 Check if targeting a specific string in command->argv works
	  }
	  if (strchr(command->argv[i], '<') != NULL)
	  {
	    input(command->argv[i+1]);
	  }
	  if (strchr(command->argv[i], '|')!= NULL)
	  {
	    // not sure if i + 1 correct
	    //  pipe(command->argv[i+1]);
	  }
	  if (strpbrk(command->argv[i], ">>")!= NULL)
	  {
	    append(command->argv[i-1], command->argv[i+1]);
          }
	}
}

void output(char *command){
  int newfd;
  if(newfd = open(command, O_CREAT | O_TRUNC | O_WRONLY, 0644)< 0)
  {
    perror(command);
    exit(1);
  }
  dup2(newfd,1);
}

void input(char *command)
{
  int newfd;
  if(newfd = open(command, O_RDONLY)<0)
  {
    perror(command);
    exit(1);
  }
  dup2(newfd,0);
}

void ExecPipe()
{
	;
}

void append(char *input, char *file)
{
  FILE *fp;
 
  fp = fopen(file, "a+");
   
  fputs(input, fp);
  fclose(fp);
}
	// check command standard input
	// if (strchr(inputString, '<') != NULL)
	// {
	// 	newfd = open((command, O_CREAT |O_TRUNC | O_WRONLY, 0644)) < 0);
	// 	// No if statement for fail checking, brackets just exist here
	// 	{
	// 		// failed
	// 		perror(command);
	// 		exit(1);
	// 	}
	// 	dup2(newfd, 0);
	// }

	// check pipe
	// TODO: Check for pipe symbol
	//		 Check in command->argv[] instead
	// if (strchr(command, '|') != NULL)
	// {
	// 	;
	// }
	// check append
	// TODO: Implement append
	// if (strpbrk(command, ">>") != NULL)
	// {
	// 	newfd = open((command, O_CREAT |O_TRUNC | O_WRONLY, 0644)) < 0);
	// 	// No if statement for fail checking, brackets just exist here
	// 	{
	// 		// failed
	// 		perror(command);
	// 		exit(1);
	// 	}
	// 	dup2(newfd, 0);
	// }
	// check pipe
	// TODO: Check pipe already exists above, maybe loop?
	// if (strchr(command, '|') != NULL)
	// {
	// 	;
	// }
	// check append
	// TODO: Check append already exists above, maybe loop?
	// if (strpbrk(command, ">>") != NULL)
	// {
	// 	;
	// }

// Environment varibles
// TODO: Add this function to CommandStruct
//		 Environment Variables can just be a part of the struct
// void varibles(char str, int count)
// {
// 	char var[1000];
// 	var[count] = str;
// }