#pragma once

#define CMDLINE_MAX_SIZE 1024 /* max length of a single command line */
#define ARGS_MAX_QUANTITY 128 /* max args on a command line */
#define BUFFER_MAX_SIZE 64	  /* max size of a buffer which contains parsed arguments */
#define CMDLINE_DIV ' \t\r\n\a'
#define CMDLINE_HISTORY_MAX_QUANTITY 256
#define JOBS_MAX_QUANTITY 16
#define PATH_MAX_SIZE 256
#define LS_BUF_SIZE 1024
#define REDIRECT_FILENAME_MAX_SIZE 64 /* redirection filename */
#define REDIRECT_ARG_MAX_SIZE 16	  /* redirection argument */

#define UNDF 0 /* undefined */
#define FG 1   /* running in foreground */
#define BG 2   /* running in background */
#define ST 3   /* stopped */

#define REDIRECT_NO 0  /* no redirection */
#define REDIRECT_OUT 1 /* redirect output */
#define REDIRECT_IN 2  /* redirect input */

/* job_t - The job struct */
struct job_t
{
	pid_t pid;						/* job PID */
	int jid;						/* job ID [1, 2, ...] */
	int state;						/* UNDEF, BG, FG, or ST */
	char cmdline[CMDLINE_MAX_SIZE]; /* command line */
};

/* readline - Get the command line */
char *readline();

/* parseline - Evaluate the command line that the user has just typed in */
int parseline(char *cmdline, char **args);

/* check_redirect - check if the command contains redirection */
int check_redirect(char **args, char *redirect_filename, char **redirect_args);

/* execute - Execute the command line */
int execute(char *cmdline, char **args);

/* builtin functions - Handle built-in command */
int built_in(char **args);
int builtin_cd(char **args);
int builtin_history(char **args);
int builtin_jobs(char **args);
int builtin_mytop(char **args);

/* do_bgfg - Execute background/foregroung tasks */
int do_bgfg(char **args);

/* waitfg - Wait foreground jobs to finish */
void waitfg(pid_t pid);

/* initjobs - Initialize the job list */
void initjobs(struct job_t *jobs);

/* addjob - Add jobs to joblist */
int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline);

/* listjobs - Print the job list */
void listjobs(struct job_t *jobs);

/* deletejob - Delete a job whose PID=pid from the job list */
int deletejob(struct job_t *jobs, pid_t pid);

/* clearjob - Clear the entries in a job struct */
void clearjob(struct job_t *job);

/* pide2jid - Map process ID to job ID*/
int pid2jid(pid_t pid);

/* fgpid - Return PID of current foreground job, 0 if no such job */
pid_t fgpid(struct job_t *jobs);

/* getjobpid - Find a job (by PID) on the job list */
struct job_t *getjobpid(struct job_t *jobs, pid_t pid);

/* getjobjid  - Find a job (by JID) on the job list */
struct job_t *getjobjid(struct job_t *jobs, int jid);

/* maxjid - Returns largest allocated job ID */
int maxjid(struct job_t *jobs);

/* Signal - wrapper for the sigaction function */
typedef void handler_t(int);
handler_t *Signal(int signum, handler_t *handler);

/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int signal);

/* 
 * sigint_handler - The kernel sends a SIGINT to the shell whenver the
 *    user types ctrl-c at the keyboard.  Catch it and send it along
 *    to the foreground job.  
 */
void sigint_handler(int signal);

/*
 * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
 *     the user types ctrl-z at the keyboard. Catch it and suspend the
 *     foreground job by sending it a SIGTSTP.  
 */

void sigtstp_handler(int signal);

/*
 * sigquit_handler - The driver program can gracefully terminate the
 *    child shell by sending it a SIGQUIT signal.
 */
void sigquit_handler(int signal);