#include <moon/Syscall.h>
#include <os/ArgumentParser.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

static const char* syscall_list[] = {
#undef __enumerate
#define __enumerate(name) #name,
    enumerate_syscalls(__enumerate)
#undef __enumerate
};

int random_syscall()
{
    int sys;

    while (true)
    {
        sys = rand() % Syscalls::__count;
        if (sys == SYS_exit || sys == SYS_usleep || sys == SYS_fork || sys == SYS_sigreturn) continue;
        break;
    }

    return sys;
}

void random_args(int args[5])
{
    for (int i = 0; i < 5; i++) { args[i] = rand(); }
}

int main(int argc, char** argv)
{
    StringView times_sv = "20"_sv;
    StringView interval_sv = "1000"_sv;

    os::ArgumentParser parser;
    parser.add_description("System call fuzzer (invokes system calls with random arguments to test system stability)");
    parser.add_system_program_info("sysfuzz"_sv);
    parser.add_value_argument(times_sv, 't', "times"_sv, "the number of syscalls to invoke"_sv);
    parser.add_value_argument(interval_sv, 'i', "interval"_sv,
                              "the interval between system calls (in milliseconds)"_sv);
    parser.parse(argc, argv);

    srand((unsigned)time(nullptr));

    int times = atoi(times_sv.chars());
    int interval = atoi(interval_sv.chars());

    while (times--)
    {
        int args[5];
        int sys = random_syscall();
        random_args(args);

        printf("%s(%d, %d, %d, %d, %d) -> ", syscall_list[sys], args[0], args[1], args[2], args[3], args[4]);

        long rc = syscall(sys, args[0], args[1], args[2], args[3], args[4]);

        if (rc < 0)
        {
            int error = (int)-rc;
            printf("%ld (%s)\n", rc, strerror(error));
        }
        else
            printf("%ld\n", rc);

        usleep(interval * 1000);
    }
}