#include "utils.h"

std::wstring StringToWString(const std::string& str) {
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    return converter.from_bytes(str);
}

std::string WStringToString(const std::wstring& wstr) {
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    return converter.to_bytes(wstr);
}

std::wstring EscapeArgument(const std::wstring& arg) {
    if (arg.empty()) {
        return L"\"\"";
    }

    // Если аргумент не содержит пробелов, табов и кавычек - возвращаем как есть
    if (arg.find_first_of(L" \t\n\v\"") == std::wstring::npos) {
        return arg;
    }

    // Аргумент нужно заключить в кавычки и экранировать внутренние кавычки
    std::wstring escaped = L"\"";

    for (size_t i = 0; i < arg.length(); i++) {
        int backslashes = 0;

        // Считаем количество обратных слешей перед кавычкой
        while (i < arg.length() && arg[i] == L'\\') {
            backslashes++;
            i++;
        }

        if (i == arg.length()) {
            // Завершающие обратные слеши
            escaped.append(backslashes * 2, L'\\');
            break;
        } else if (arg[i] == L'"') {
            // Кавычка - удваиваем количество обратных слешей и добавляем \"
            escaped.append(backslashes * 2, L'\\');
            escaped += L"\\\"";
        } else {
            // Обычный символ
            escaped.append(backslashes, L'\\');
            escaped += arg[i];
        }
    }

    escaped += L'"';
    return escaped;
}

std::wstring GetCommandLineArgumentsW() {

    int argc = 0;
    LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);

    std::wstring result;
    if (argv) {
        for (int i = 1; i < argc; i++) {
            result += EscapeArgument(argv[i]);
            result += L' ';
        }
        LocalFree(argv);
    }

    return result;
}


std::wstring GetSelfDirectoryW() {
    wchar_t buffer[MAX_PATH];
    GetModuleFileNameW(NULL, buffer, MAX_PATH);

    std::wstring path(buffer);
    size_t pos = path.find_last_of(L"\\");
    if (pos != std::wstring::npos) {
        return path.substr(0, pos);
    }
    return L"";
}

bool FileExists(const char* path) {
    DWORD attr = GetFileAttributesA(path);
    return (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_DIRECTORY);
}

bool IsTargetProcess(const wchar_t* processName, const std::vector<std::string>& targetProcesses) {
    for (const auto& target : targetProcesses) {
        if (_wcsicmp(processName, StringToWString(target).c_str()) == 0) {
            return true;
        }
    }
    return false;
}

BOOL GetProcessCreationTime(DWORD dwProcessId, FILETIME& CreationTime)
{
    BOOL bResult = false;
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId);
    if (hProcess)
    {
        FILETIME Ignore;
        bResult = GetProcessTimes(hProcess, &CreationTime, &Ignore, &Ignore, &Ignore);
        CloseHandle(hProcess);
    }
    return bResult;
}
