#include "utils.h"
#include <stdio.h>
#include <ctype.h>

bool generate_browser_mimic_pipe_name(const wchar_t* browser_type, wchar_t* pipe_name, size_t len) {
    if (!browser_type || !pipe_name) return false;

    DWORD pid = GetCurrentProcessId();
    DWORD tid = GetCurrentThreadId();
    DWORD tick = GetTickCount();

    DWORD id1 = (pid ^ tick) & 0xFFFF;
    DWORD id2 = (tid ^ (tick >> 16)) & 0xFFFF;
    DWORD id3 = ((pid << 8) ^ tid) & 0xFFFF;

    wchar_t browser_lower[64];
    wcsncpy_s(browser_lower, 64, browser_type, _TRUNCATE);
    for (wchar_t* p = browser_lower; *p; p++) {
        *p = towlower(*p);
    }

    if (wcscmp(browser_lower, L"chrome") == 0) {
        const wchar_t* patterns[] = {
            L"\\\\.\\pipe\\chrome.sync.%u.%u.%04X",
            L"\\\\.\\pipe\\chrome.nacl.%u_%04X",
            L"\\\\.\\pipe\\mojo.%u.%u.%04X.chrome"
        };
        int idx = (id1 + id2) % 3;

        if (idx == 1) {
            swprintf_s(pipe_name, len, patterns[idx], id1, id3);
        }
        else {
            swprintf_s(pipe_name, len, patterns[idx], id1, id2, id3);
        }
    }
    else if (wcscmp(browser_lower, L"brave") == 0) {
        const wchar_t* patterns[] = {
            L"\\\\.\\pipe\\brave.sync.%u.%u",
            L"\\\\.\\pipe\\mojo.%u.%u.brave",
            L"\\\\.\\pipe\\brave.crashpad_%u"
        };
        int idx = id3 % 3;

        if (idx == 2) {
            swprintf_s(pipe_name, len, patterns[idx], id1);
        }
        else {
            swprintf_s(pipe_name, len, patterns[idx], id1, id2);
        }
    }
    else {
        swprintf_s(pipe_name, len, L"\\\\.\\pipe\\chromium.ipc.%u.%u", id1, id2);
    }

    return true;
}

bool create_directory_recursive(const wchar_t* path) {
    if (!path) return false;

    wchar_t temp[MAX_PATH_LEN];
    wcsncpy_s(temp, MAX_PATH_LEN, path, _TRUNCATE);

    for (wchar_t* p = temp; *p; p++) {
        if (*p == L'/' || *p == L'\\') {
            wchar_t saved = *p;
            *p = L'\0';

            DWORD attrs = GetFileAttributesW(temp);
            if (attrs == INVALID_FILE_ATTRIBUTES) {
                if (!CreateDirectoryW(temp, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
                    return false;
                }
            }

            *p = saved;
        }
    }

    DWORD attrs = GetFileAttributesW(temp);
    if (attrs == INVALID_FILE_ATTRIBUTES) {
        return CreateDirectoryW(temp, NULL) || GetLastError() == ERROR_ALREADY_EXISTS;
    }

    return true;
}

bool file_exists(const wchar_t* path) {
    if (!path) return false;
    DWORD attrs = GetFileAttributesW(path);
    return (attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY));
}