#include "types.h"
#include "x86.h"
#include "defs.h"
#include "date.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"

int sys_fork(void)
{
    return fork();
}

int sys_exit(void)
{
    exit();
    return 0; // not reached
}

int sys_wait(void)
{
    return wait();
}

int sys_kill(void)
{
    int pid;

    if (argint(0, &pid) < 0)
    {
        return -1;
    }
    return kill(pid);
}

int sys_getpid(void)
{
    return myproc()->pid;
}

int sys_sbrk(void)
{
    int addr;
    int n;

    if (argint(0, &n) < 0)
    {
        return -1;
    }
    addr = myproc()->sz;
    if (growproc(n) < 0)
    {
        return -1;
    }
    return addr;
}

int sys_sleep(void)
{
    int n;
    uint ticks0;

    if (argint(0, &n) < 0)
    {
        return -1;
    }
    acquire(&tickslock);
    ticks0 = ticks;
    while (ticks - ticks0 < n)
    {
        if (myproc()->killed)
        {
            release(&tickslock);
            return -1;
        }
        sleep(&ticks, &tickslock);
    }
    release(&tickslock);
    return 0;
}

// return how many clock tick interrupts have occurred
// since start.
int sys_uptime(void)
{
    uint xticks;

    acquire(&tickslock);
    xticks = ticks;
    release(&tickslock);
    return xticks;
}

// System call i used to debug and test the consoles, it returns useful information in relation to the current console/process
int sys_greeting(void)
{    
    cprintf("Hello! here is the info you requested...\n");
    cprintf("Using Console: %d\n", getcurrentconsoleindex());
    cprintf("Current PID: %d\n", myproc()->pid);
    cprintf("Current Parent PID: %d\n", myproc()->parent->pid);
    cprintf("Process Console: %d\n", getconsoleindex(myproc()->consoleptr));
    return 0;
}

// System call to shutdown or restart the OS
int sys_shutdown(void)
{
    int restart;
    if (argint(0, &restart) < 0)
    {
        return -1;
    }

    if (restart == 1)
    {
        unsigned char good = 0x02;
        while (good & 0x02) {
            good = inb(0x64);
        }
        outb(0x64, 0xFE);
    }
    else
    {
        outw(0x604, 0x2000);
    }
    return 0;
}

// System call for handling the new screen user app
int sys_screen(void) 
{
    struct proc *curproc = myproc();
    int result = 0;
    struct vconsole* consoleptr = 0;
    int bgcol;
    char *title;

    // Get the background color value
    if (argint(1, &bgcol) < 0)
    {
        return -1;
    }

    // Get the title arg value
    if (argstr(0, &title) < 0)
    {
        return -1;
    }

    // Try to setup an unused console from the pool
    if ((consoleptr = newconsole(title, bgcol)) != 0)
    {   
        // New console was successful, set the pointer and switch to it
        curproc->consoleptr = consoleptr;                
        switchtoconsole(consoleptr);                
        result = 1;
    }    
    else
    {
        cprintf("screen: failed to create a new console\n");
    }
    return result;
}

// System call to clear the screen
int sys_cls(void)
{
    clearscreen(0);
    return 0;
}