#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <conio.h>

#if defined(__WATCOMC__)
#include <process.h>
#endif

#include "pastfetch.h"

#if defined(__WATCOMC__)
extern unsigned char _nullarea[32];

static void reset_null_sentinel(void) {
    // Restore the Watcom null-pointer guard pattern so spurious NULL reports clear
    memset(_nullarea, 0x01, sizeof(_nullarea));
}
#endif

static void safe_exit(int code, int hard_exit) {
    // Flush output, clear null sentinel, and terminate.
    fflush(NULL);
#if defined(__WATCOMC__)
    reset_null_sentinel();
#endif
    if (hard_exit) {
        _exit(code);
    } else {
        exit(code);
    }
}

//Check for a Ctrl+Q keypress in the BIOS buffer to force a fast exit
static int force_quit_requested(void) {
    if (!kbhit()) {
        return 0;
    }
    {
        int ch = getch();
        if (ch == 0 || ch == 0xE0) {
            int scan = getch();
            return scan == 0x10; // Ctrl+Q scan code
        }
        return ch == 0x11; // Ctrl+Q ASCII
    }
}

// Parse command-line options into RunOptions
static void parse_args(int argc, char **argv, RunOptions *options) {
    int i;
    memset(options, 0, sizeof(*options));
    // Default to fast exit to avoid stuck prompts on IBM PC DOS and Novell
    // but only sometimes????
    options->hard_exit = 1;

    for (i = 1; i < argc; ++i) {
        if (str_equals_ci(argv[i], "/nologo") || strcmp(argv[i], "--no-logo") == 0) {
            options->no_logo = 1;
        } else if (str_equals_ci(argv[i], "/list") || strcmp(argv[i], "--list") == 0) {
            options->list_only = 1;
        } else if (str_equals_ci(argv[i], "/logo") || strcmp(argv[i], "--logo") == 0) {
            if (i + 1 >= argc) {
                fputs("Error: /logo requires a logo name.\n", stderr);
                safe_exit(1, options->hard_exit);
            }
            if (!logo_name_exists(argv[i + 1], options->logo_override,
                                  sizeof(options->logo_override))) {
                fputs("Error: unknown logo name. Use /list to view available logos.\n", stderr);
                safe_exit(1, options->hard_exit);
            }
            ++i;
        } else if (str_equals_ci(argv[i], "/noansi") || strcmp(argv[i], "--noansi") == 0) {
            options->force_ascii = 1;
        } else if (str_equals_ci(argv[i], "/r") || strcmp(argv[i], "--prompt-fix") == 0) {
            options->prompt_fix = 1;
        } else if (str_equals_ci(argv[i], "/safe") || str_equals_ci(argv[i], "/safeexit")) {
            options->hard_exit = 0;
        } else if (strcmp(argv[i], "/?") == 0) {
            puts("pastfetch - DOS system information fetcher");
            puts("");
            puts("Usage: pastfetch [options]");
            puts("");
            puts("Options:");
            puts("  /nologo      Disable ANSI logo output");
            puts("  /list        Show available logo names");
            puts("  /logo NAME   Force a specific logo (NAME from /list)");
            puts("  /noansi      Force ASCII logo even if ANSI is available");
            puts("  /r           Emit an extra ANSI reset/newline for stubborn shells");
            puts("  /safe        Use normal CRT cleanup/exit (default is fast exit)");
            puts("  Ctrl+Q       Force a fast exit even if /safe was used");
            puts("  /?           Show this help text");
            safe_exit(0, options->hard_exit);
        }
    }
}

// Entry point: parse args, detect system, and render output.
int main(int argc, char **argv) {
    SystemInfo info;
    StringList drivers;
    RunOptions options;

    memset(&info, 0, sizeof(info));
    strlist_init(&drivers);

    parse_args(argc, argv, &options);

    if (options.list_only) {
        list_available_logos();
    } else {
        detect_system(&info, &drivers);
        render_system(&info, &drivers, &options);
    }

    strlist_free(&drivers);
    if (force_quit_requested()) {
        options.hard_exit = 1;
    }
    safe_exit(0, options.hard_exit);
    return 0; // yes, yes, compiler shut up already
}
