#include "rlang.h"

r_obj* eval_with_x(r_obj* call, r_obj* x);

static r_obj* is_installed_call = NULL;

bool r_is_installed(const char* pkg) {
    r_obj* installed = eval_with_x(is_installed_call, KEEP(r_chr(pkg)));
    bool out = *r_lgl_begin(installed);

    FREE(1);
    return out;
}

static r_obj* has_colour_call = NULL;

bool r_has_colour(void) {
    if (!r_is_installed("crayon")) {
        return false;
    }

    return *r_lgl_begin(r_eval(has_colour_call, r_envs.base));
}

void r_init_library_session(void) {
    is_installed_call = r_parse("requireNamespace(x, quietly = TRUE)");
    r_preserve(is_installed_call);

    has_colour_call = r_parse("crayon::has_color()");
    r_preserve(has_colour_call);
}

#ifdef _WIN32

#include <windows.h>
#include <tlhelp32.h>

r_obj* r_getppid(void) {
    DWORD pid = GetCurrentProcessId();
    HANDLE handle = NULL;
    PROCESSENTRY32W pe = {0};

    pe.dwSize = sizeof(PROCESSENTRY32W);
    handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (handle == INVALID_HANDLE_VALUE) {
        r_abort("Can't query parent pid.");
    }

    if (Process32FirstW(handle, &pe)) {
        do {
            if (pe.th32ProcessID == pid) {
                DWORD ppid = pe.th32ParentProcessID;
                CloseHandle(handle);
                return r_int(ppid);
            }
        } while (Process32NextW(handle, &pe));
    }

    /* Should not get here */
    CloseHandle(handle);
    r_stop_internal("Can't find my own process.");
    return r_null;
}

#else

#include <unistd.h>

r_obj* r_getppid(void) {
    return r_int(getppid());
}

#endif
