//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// system_utils_win.cpp: Implementation of OS-specific functions for Windows

#include "system_utils.h"

#include <stdarg.h>
#include <windows.h>
#include <array>
#include <vector>

namespace angle
{

namespace
{

std::string GetPath(HMODULE module)
{
    std::array<wchar_t, MAX_PATH> executableFileBuf;
    DWORD executablePathLen = GetModuleFileNameW(module, executableFileBuf.data(),
                                                 static_cast<DWORD>(executableFileBuf.size()));
    return Narrow(executablePathLen > 0 ? executableFileBuf.data() : L"");
}

std::string GetDirectory(HMODULE module)
{
    std::string executablePath = GetPath(module);
    size_t lastPathSepLoc      = executablePath.find_last_of("\\/");
    return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
}

}  // anonymous namespace

std::string GetExecutablePath()
{
    return GetPath(nullptr);
}

std::string GetExecutableDirectory()
{
    return GetDirectory(nullptr);
}

const char *GetSharedLibraryExtension()
{
    return "dll";
}

Optional<std::string> GetCWD()
{
    std::array<wchar_t, MAX_PATH> pathBuf;
    DWORD result = GetCurrentDirectoryW(static_cast<DWORD>(pathBuf.size()), pathBuf.data());
    if (result == 0)
    {
        return Optional<std::string>::Invalid();
    }
    return Narrow(pathBuf.data());
}

bool SetCWD(const char *dirName)
{
    return (SetCurrentDirectoryW(Widen(dirName).c_str()) == TRUE);
}

const char *GetPathSeparatorForEnvironmentVar()
{
    return ";";
}

double GetCurrentSystemTime()
{
    LARGE_INTEGER frequency = {};
    QueryPerformanceFrequency(&frequency);

    LARGE_INTEGER curTime;
    QueryPerformanceCounter(&curTime);

    return static_cast<double>(curTime.QuadPart) / frequency.QuadPart;
}

double GetCurrentProcessCpuTime()
{
    FILETIME creationTime = {};
    FILETIME exitTime     = {};
    FILETIME kernelTime   = {};
    FILETIME userTime     = {};

    // Note this will not give accurate results if the current thread is
    // scheduled for less than the tick rate, which is often 15 ms. In that
    // case, GetProcessTimes will not return different values, making it
    // possible to end up with 0 ms for a process that takes 93% of a core
    // (14/15 ms)!  An alternative is QueryProcessCycleTime but there is no
    // simple way to convert cycles back to seconds, and on top of that, it's
    // not supported pre-Windows Vista.

    // Returns 100-ns intervals, so we want to divide by 1e7 to get seconds
    GetProcessTimes(GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime);

    ULARGE_INTEGER kernelInt64;
    kernelInt64.LowPart      = kernelTime.dwLowDateTime;
    kernelInt64.HighPart     = kernelTime.dwHighDateTime;
    double systemTimeSeconds = static_cast<double>(kernelInt64.QuadPart) * 1e-7;

    ULARGE_INTEGER userInt64;
    userInt64.LowPart      = userTime.dwLowDateTime;
    userInt64.HighPart     = userTime.dwHighDateTime;
    double userTimeSeconds = static_cast<double>(userInt64.QuadPart) * 1e-7;

    return systemTimeSeconds + userTimeSeconds;
}

bool IsDirectory(const char *filename)
{
    WIN32_FILE_ATTRIBUTE_DATA fileInformation;

    BOOL result =
        GetFileAttributesExW(Widen(filename).c_str(), GetFileExInfoStandard, &fileInformation);
    if (result)
    {
        DWORD attribs = fileInformation.dwFileAttributes;
        return (attribs != INVALID_FILE_ATTRIBUTES) && ((attribs & FILE_ATTRIBUTE_DIRECTORY) > 0);
    }

    return false;
}

bool IsDebuggerAttached()
{
    return !!::IsDebuggerPresent();
}

void BreakDebugger()
{
    __debugbreak();
}

const char *GetExecutableExtension()
{
    return ".exe";
}

char GetPathSeparator()
{
    return '\\';
}

std::string GetModuleDirectory()
{
// GetModuleHandleEx is unavailable on UWP
#if !defined(ANGLE_IS_WINUWP)
    static int placeholderSymbol = 0;
    HMODULE module               = nullptr;
    if (GetModuleHandleExW(
            GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            reinterpret_cast<LPCWSTR>(&placeholderSymbol), &module))
    {
        return GetDirectory(module);
    }
#endif
    return GetDirectory(nullptr);
}

std::string GetRootDirectory()
{
    return "C:\\";
}

std::string GetLibraryPath(void *libraryHandle)
{
    if (!libraryHandle)
    {
        return "";
    }

    std::array<wchar_t, MAX_PATH> buffer;
    if (GetModuleFileNameW(reinterpret_cast<HMODULE>(libraryHandle), buffer.data(),
                           buffer.size()) == 0)
    {
        return "";
    }

    return Narrow(buffer.data());
}

void *GetLibrarySymbol(void *libraryHandle, const char *symbolName)
{
    if (!libraryHandle)
    {
        fprintf(stderr, "Module was not loaded\n");
        return nullptr;
    }

    return reinterpret_cast<void *>(
        GetProcAddress(reinterpret_cast<HMODULE>(libraryHandle), symbolName));
}

void CloseSystemLibrary(void *libraryHandle)
{
    if (libraryHandle)
    {
        FreeLibrary(reinterpret_cast<HMODULE>(libraryHandle));
    }
}
std::string Narrow(const std::wstring_view &utf16)
{
    if (utf16.empty())
    {
        return {};
    }
    int requiredSize = WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()),
                                           nullptr, 0, nullptr, nullptr);
    std::string utf8(requiredSize, '\0');
    WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), &utf8[0],
                        requiredSize, nullptr, nullptr);
    return utf8;
}

std::wstring Widen(const std::string_view &utf8)
{
    if (utf8.empty())
    {
        return {};
    }
    int requiredSize =
        MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), nullptr, 0);
    std::wstring utf16(requiredSize, L'\0');
    MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), &utf16[0],
                        requiredSize);
    return utf16;
}

}  // namespace angle
