#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "hal/hal.h"
#include "syscall.h"
#include "vfs.h"
#include "errors.h"
#include "sysdefs/dev.h"
#include "vfs/vfs.h"
#include "spinlock/spinlock.h"
#include "dev/dev.h"
#include "proc/proc.h"
#include "storedev/storedev.h"
#include "util/util.h"

int32_t SYSCALL4(sys_vfsmount, mountpoint1, fstypestr1, devid1, format1) {
  int32_t ret = E_OK;
  char *mountpoint = (char *)mountpoint1;
  char *fstypestr = (char *)fstypestr1;
  Dev_t *dev = (Dev_t *)devid1;
  bool format = (bool)format1;

  if (mountpoint == NULL) { ret = E_INVALIDARGUMENT; goto done; }
  if (fstypestr == NULL) { ret = E_INVALIDARGUMENT; goto done; }
  if (dev == NULL) { ret = E_INVALIDARGUMENT; goto done; }

  if (*dev >= PROC_DEVHANDLES_MAX) { ret = E_INVALIDARGUMENT; goto done; }

  int32_t fstype;

  if (hal_strcmp(fstypestr, "LittleFS") == 0) {
    fstype = VFS_LITTLEFS;
  } else {
    ret = E_INVALIDARGUMENT;
    goto done;
  }

  spinlock_acquire(&PROCS.spinlock);
  Proc *proc = NULL;
  LL_FINDPROP(PROCS.procs, proc, pid, _caller_pid);
  spinlock_release(&PROCS.spinlock);

  Dev *dp = proc->devs[*dev];
  if (dp == NULL) { ret = E_NOENTRY; goto done; }

  StoreDev *sd = (StoreDev *)dp->extra;
  if (sd != NULL && sd->_magic != STOREDEV_MAGIC) { ret = E_NOENTRY; goto done; }

  ret = vfs_mount(mountpoint, fstype, sd, format);

done:
  return ret;
}

int32_t SYSCALL1(sys_vfsunmount, mountpoint1) {
  int32_t ret = E_OK;
  char *mountpoint = (char *)mountpoint1;
  
  if (mountpoint == NULL) { ret = E_INVALIDARGUMENT; goto done; }

  ret = vfs_unmount(mountpoint);

done:
  return ret;
}
