#include <stdint.h>
#include <system/system.h>
#include <syscall/syscall.h>
#include <sysdefs/syscall.h>
#include <sysdefs/fs.h>
#include <sysdefs/proc.h>
#include <sysdefs/dev.h>
#include <uprintf.h>

void debugprint(const char *string) {
  syscall(SYS_DEBUGPRINT, (uint64_t)string, 0, 0, 0, 0, 0);
}

int32_t mman_map(uint8_t *addr, size_t size, uint64_t prot, uint64_t flags, uint8_t **out) {
  return syscall(SYS_MMAN_MAP, (uint64_t)addr, (uint64_t)size, prot, flags, (uint64_t)out, 0);
}

int32_t mman_unmap(uint8_t *addr) {
  return syscall(SYS_MMAN_UNMAP, (uint64_t)addr, 0, 0, 0, 0, 0);
}

int32_t schedrelease(void) {
  return syscall(SYS_SCHEDRELEASE, 0, 0, 0, 0, 0, 0);
}

int32_t rand(void) {
  return syscall(SYS_RAND, 0, 0, 0, 0, 0, 0);
}

int32_t vfsmount(char *mountpoint, char *fstype, Dev_t *dev, bool format) {
  return syscall(SYS_VFSMOUNT, (uint64_t)mountpoint, (uint64_t)fstype, (uint64_t)dev, (uint64_t)format, 0, 0);
}

int32_t vfsunmount(char *mountpoint) {
  return syscall(SYS_VFSUNMOUNT, (uint64_t)mountpoint, 0, 0, 0, 0, 0);
}

int32_t ipc_piperead(PID_t pid, uint64_t pipenum, uint8_t *const buffer, size_t len) {
  return syscall(SYS_IPC_PIPEREAD, (uint64_t)pid, (uint64_t)pipenum, (uint64_t)buffer, (uint64_t)len, 0, 0);
}

int32_t ipc_pipewrite(PID_t pid, uint64_t pipenum, const uint8_t *buffer, size_t len) {
  return syscall(SYS_IPC_PIPEWRITE, (uint64_t)pid, (uint64_t)pipenum, (uint64_t)buffer, (uint64_t)len, 0, 0);
}

int32_t ipc_pipemake(uint64_t pipenum) {
  return syscall(SYS_IPC_PIPEMAKE, pipenum, 0, 0, 0, 0, 0);
}

int32_t ipc_pipedelete(uint64_t pipenum) {
  return syscall(SYS_IPC_PIPEDELETE, pipenum, 0, 0, 0, 0, 0);
}

int32_t ipc_pipeconnect(PID_t pid1, uint64_t pipenum1, PID_t pid2, uint64_t pipenum2) {
  return syscall(SYS_IPC_PIPECONNECT, pid1, pipenum1, pid2, pipenum2, 0, 0);
}

int32_t proc_kill(PID_t pid) {
  return syscall(SYS_PROC_KILL, (uint64_t)pid, 0, 0, 0, 0, 0);
}

int32_t proc_spawn(char *path, char **args1, size_t argslen1) {
  return syscall(SYS_PROC_SPAWN, (uint64_t)path, (uint64_t)args1, (uint64_t)argslen1, 0, 0, 0);
}

int32_t proc_pollstate(PID_t pid) {
  return syscall(SYS_PROC_POLLSTATE, (uint64_t)pid, 0, 0, 0, 0, 0);
}

int32_t proc_getpid(void) {
  return syscall(SYS_PROC_GETPID, 0, 0, 0, 0, 0, 0);
}

int32_t proc_run(PID_t pid) {
  return syscall(SYS_PROC_RUN, (uint64_t)pid, 0, 0, 0, 0, 0);
}

int32_t proc_arglen(PID_t pid) {
  return syscall(SYS_PROC_ARGLEN, (uint64_t)pid, 0, 0, 0, 0, 0);
}

int32_t proc_argv(PID_t pid, size_t *argslen1, char **argbuf1, size_t maxargs) {
  return syscall(SYS_PROC_ARGV, (uint64_t)pid, (uint64_t)argslen1, (uint64_t)argbuf1, (uint64_t)maxargs, 0, 0);
}

int32_t proc_listsize(void) {
  return syscall(SYS_PROC_LISTSIZE, 0, 0, 0, 0, 0, 0);
}

int32_t proc_stat(size_t idx, ProcStat *pstat) {
  return syscall(SYS_PROC_STAT, (uint64_t)idx, (uint64_t)pstat, 0, 0, 0, 0);
}

int32_t fs_openf(char *path, uint64_t flags) {
  return syscall(SYS_FS_OPENF, (uint64_t)path, flags, 0, 0, 0, 0);
}

int32_t fs_closef(int32_t fsh) {
  return syscall(SYS_FS_CLOSEF, (uint64_t)fsh, 0, 0, 0, 0, 0);
}

int32_t fs_write(int32_t fsh, const uint8_t *buffer, size_t len, size_t off) {
  return syscall(SYS_FS_WRITE, (uint64_t)fsh, (uint64_t)buffer, (uint64_t)len, (uint64_t)off, 0, 0);
}

int32_t fs_read(int32_t fsh, uint8_t *const buffer, size_t len, size_t off) {
  return syscall(SYS_FS_READ, (uint64_t)fsh, (uint64_t)buffer, (uint64_t)len, (uint64_t)off, 0, 0);
}

int32_t fs_stat(char *path, FsStat *statbuf) {
  return syscall(SYS_FS_STAT, (uint64_t)path, (uint64_t)statbuf, 0, 0, 0, 0);
}

int32_t fs_fetchdirent(char *path, FsDirent *direntbuf, size_t idx) {
  return syscall(SYS_FS_FETCHDIRENT, (uint64_t)path, (uint64_t)direntbuf, (uint64_t)idx, 0, 0, 0);
}

int32_t fs_mkdir(char *path) {
  return syscall(SYS_FS_MKDIR, (uint64_t)path, 0, 0, 0, 0, 0);
}

int32_t fs_delete(char *path) {
  return syscall(SYS_FS_DELETE, (uint64_t)path, 0, 0, 0, 0, 0);
}

int32_t dev_gethandle(Dev_t *dev, char *name) {
  return syscall(SYS_DEV_GETHANDLE, (uint64_t)dev, (uint64_t)name, 0, 0, 0, 0);
}

int32_t dev_listsize(void) {
  return syscall(SYS_DEV_LISTSIZE, 0, 0, 0, 0, 0, 0);
}

int32_t dev_stat(DevStat *devstatbuf, size_t idx) {
  return syscall(SYS_DEV_STAT, (uint64_t)devstatbuf, (uint64_t)idx, 0, 0, 0, 0);
}

int32_t dev_cmd(Dev_t *dev, uint64_t cmd, void *buf, size_t len) {
  return syscall(SYS_DEV_CMD, (uint64_t)dev, (uint64_t)cmd, (uint64_t)buf, (uint64_t)len, 0, 0);
}

int32_t time(Time *time) {
  return syscall(SYS_TIME, (uint64_t)time, 0, 0, 0, 0, 0);
}

int32_t ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port) {
  return syscall(SYS_IPC_NETSOCKMAKE, (uint64_t)net, (uint64_t)proto, (uint64_t)port, 0, 0, 0);
}

int32_t ipc_netsocklisten(uint64_t netsock, size_t maxlisteners) {
  return syscall(SYS_IPC_NETSOCKLISTEN, (uint64_t)netsock, (uint64_t)maxlisteners, 0, 0, 0, 0);
}

int32_t ipc_netsockpollev(uint64_t netsock) {
  return syscall(SYS_IPC_NETSOCKPOLLEV, (uint64_t)netsock, 0, 0, 0, 0, 0);
}
