//
// 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.h: declaration of OS-specific utility functions

#ifndef COMMON_SYSTEM_UTILS_H_
#define COMMON_SYSTEM_UTILS_H_

#include "common/Optional.h"
#include "common/angleutils.h"

#include <functional>
#include <string>
#include <string_view>

namespace angle
{
std::string GetExecutableName();
std::string GetExecutablePath();
std::string GetExecutableDirectory();
std::string GetModuleDirectory();
const char *GetSharedLibraryExtension();
const char *GetExecutableExtension();
char GetPathSeparator();
Optional<std::string> GetCWD();
bool SetCWD(const char *dirName);
bool SetEnvironmentVar(const char *variableName, const char *value);
bool UnsetEnvironmentVar(const char *variableName);
bool GetBoolEnvironmentVar(const char *variableName);
std::string GetEnvironmentVar(const char *variableName);
std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
                                                       const char *propertyName);
std::string GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
                                                             const char *propertyName);
std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName);
const char *GetPathSeparatorForEnvironmentVar();
bool PrependPathToEnvironmentVar(const char *variableName, const char *path);
bool IsDirectory(const char *filename);
bool IsFullPath(std::string dirName);
std::string GetRootDirectory();
std::string ConcatenatePath(std::string first, std::string second);

// Get absolute time in seconds.  Use this function to get an absolute time with an unknown origin.
double GetCurrentSystemTime();
// Get CPU time for current process in seconds.
double GetCurrentProcessCpuTime();

// Run an application and get the output.  Gets a nullptr-terminated set of args to execute the
// application with, and returns the stdout and stderr outputs as well as the exit code.
//
// Pass nullptr for stdoutOut/stderrOut if you don't need to capture. exitCodeOut is required.
//
// Returns false if it fails to actually execute the application.
bool RunApp(const std::vector<const char *> &args,
            std::string *stdoutOut,
            std::string *stderrOut,
            int *exitCodeOut);

// Use SYSTEM_DIR to bypass loading ANGLE libraries with the same name as system DLLS
// (e.g. opengl32.dll)
enum class SearchType
{
    // Try to find the library in the same directory as the current module
    ModuleDir,
    // Load the library from the system directories
    SystemDir,
    // Get a reference to an already loaded shared library.
    AlreadyLoaded,
};

void *OpenSystemLibrary(const char *libraryName, SearchType searchType);
void *OpenSystemLibraryWithExtension(const char *libraryName, SearchType searchType);
void *OpenSystemLibraryAndGetError(const char *libraryName,
                                   SearchType searchType,
                                   std::string *errorOut);
void *OpenSystemLibraryWithExtensionAndGetError(const char *libraryName,
                                                SearchType searchType,
                                                std::string *errorOut);

void *GetLibrarySymbol(void *libraryHandle, const char *symbolName);
std::string GetLibraryPath(void *libraryHandle);
void CloseSystemLibrary(void *libraryHandle);

class Library : angle::NonCopyable
{
  public:
    Library() {}
    Library(void *libraryHandle) : mLibraryHandle(libraryHandle) {}
    ~Library() { close(); }

    ANGLE_NO_DISCARD bool open(const char *libraryName, SearchType searchType)
    {
        close();
        mLibraryHandle = OpenSystemLibrary(libraryName, searchType);
        return mLibraryHandle != nullptr;
    }

    ANGLE_NO_DISCARD bool openWithExtension(const char *libraryName, SearchType searchType)
    {
        close();
        mLibraryHandle = OpenSystemLibraryWithExtension(libraryName, searchType);
        return mLibraryHandle != nullptr;
    }

    ANGLE_NO_DISCARD bool openAndGetError(const char *libraryName,
                                          SearchType searchType,
                                          std::string *errorOut)
    {
        close();
        mLibraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, errorOut);
        return mLibraryHandle != nullptr;
    }

    ANGLE_NO_DISCARD bool openWithExtensionAndGetError(const char *libraryName,
                                                       SearchType searchType,
                                                       std::string *errorOut)
    {
        close();
        mLibraryHandle =
            OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, errorOut);
        return mLibraryHandle != nullptr;
    }

    void close()
    {
        if (mLibraryHandle)
        {
            CloseSystemLibrary(mLibraryHandle);
            mLibraryHandle = nullptr;
        }
    }

    void *getSymbol(const char *symbolName) { return GetLibrarySymbol(mLibraryHandle, symbolName); }

    void *getNative() const { return mLibraryHandle; }

    std::string getPath() const { return GetLibraryPath(mLibraryHandle); }

    template <typename FuncT>
    void getAs(const char *symbolName, FuncT *funcOut)
    {
        *funcOut = reinterpret_cast<FuncT>(getSymbol(symbolName));
    }

  private:
    void *mLibraryHandle = nullptr;
};

Library *OpenSharedLibrary(const char *libraryName, SearchType searchType);
Library *OpenSharedLibraryWithExtension(const char *libraryName, SearchType searchType);
Library *OpenSharedLibraryAndGetError(const char *libraryName,
                                      SearchType searchType,
                                      std::string *errorOut);
Library *OpenSharedLibraryWithExtensionAndGetError(const char *libraryName,
                                                   SearchType searchType,
                                                   std::string *errorOut);

// Returns true if the process is currently being debugged.
bool IsDebuggerAttached();

// Calls system APIs to break into the debugger.
void BreakDebugger();

bool ProtectMemory(uintptr_t start, size_t size);
bool UnprotectMemory(uintptr_t start, size_t size);

size_t GetPageSize();

// Return type of the PageFaultCallback
enum class PageFaultHandlerRangeType
{
    // The memory address was known by the page fault handler
    InRange,
    // The memory address was not in the page fault handler's range
    // and the signal will be forwarded to the default page handler.
    OutOfRange,
};

using PageFaultCallback = std::function<PageFaultHandlerRangeType(uintptr_t)>;

class PageFaultHandler : angle::NonCopyable
{
  public:
    PageFaultHandler(PageFaultCallback callback);
    virtual ~PageFaultHandler();

    // Registers OS level page fault handler for memory protection signals
    // and enables reception on PageFaultCallback
    virtual bool enable() = 0;

    // Unregisters OS level page fault handler and deactivates PageFaultCallback
    virtual bool disable() = 0;

  protected:
    PageFaultCallback mCallback;
};

// Creates single instance page fault handler
PageFaultHandler *CreatePageFaultHandler(PageFaultCallback callback);

#ifdef ANGLE_PLATFORM_WINDOWS
// Convert an UTF-16 wstring to an UTF-8 string.
std::string Narrow(const std::wstring_view &utf16);

// Convert an UTF-8 string to an UTF-16 wstring.
std::wstring Widen(const std::string_view &utf8);
#endif
}  // namespace angle

#endif  // COMMON_SYSTEM_UTILS_H_
