//
// Copyright 2019 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: Defines common utility functions

#include "util/test_utils.h"
#include "common/unsafe_buffers.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>

namespace angle
{

namespace
{
void DeleteArg(int *argc, char **argv, int argIndex)
{
    // Shift the remainder of the argv list left by one.  Note that argv has (*argc + 1) elements,
    // the last one always being NULL.  The following loop moves the trailing NULL element as well.
    for (int index = argIndex; index < *argc; ++index)
    {
        ANGLE_UNSAFE_TODO(argv[index]) = ANGLE_UNSAFE_TODO(argv[index + 1]);
    }
    (*argc)--;
}

const char *GetSingleArg(const char *flag,
                         int *argc,
                         char **argv,
                         int argIndex,
                         ArgHandling handling)
{
    if (ANGLE_UNSAFE_TODO(strstr(argv[argIndex], flag)) == ANGLE_UNSAFE_TODO(argv[argIndex]))
    {
        const char *ptr = ANGLE_UNSAFE_TODO(argv[argIndex] + strlen(flag));

        if (*ptr == '=')
        {
            if (handling == ArgHandling::Delete)
            {
                DeleteArg(argc, argv, argIndex);
            }
            return ANGLE_UNSAFE_TODO(ptr + 1);
        }

        if (*ptr == '\0' && argIndex < *argc - 1)
        {
            ptr = ANGLE_UNSAFE_TODO(argv[argIndex + 1]);
            if (handling == ArgHandling::Delete)
            {
                DeleteArg(argc, argv, argIndex);
                DeleteArg(argc, argv, argIndex);
            }
            return ptr;
        }
    }

    return nullptr;
}

using DisplayTypeInfo = std::pair<const char *, EGLint>;

const DisplayTypeInfo kDisplayTypes[] = {
    {"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE},
    {"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE},
    {"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE},
    {"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE},
    {"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE},
    {"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
    {"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
    {"vulkan-null", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
    {"webgpu", EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE},
};
}  // anonymous namespace

bool GetFileSize(const char *filePath, uint32_t *sizeOut)
{
    std::ifstream stream(filePath);
    if (!stream)
    {
        return false;
    }

    stream.seekg(0, std::ios::end);
    *sizeOut = static_cast<uint32_t>(stream.tellg());
    return true;
}

bool ReadEntireFileToString(const char *filePath, std::string *contentsOut)
{
    std::ifstream stream(filePath);
    if (!stream)
    {
        return false;
    }

    stream.seekg(0, std::ios::end);
    contentsOut->reserve(static_cast<unsigned int>(stream.tellg()));
    stream.seekg(0, std::ios::beg);

    contentsOut->assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());

    return true;
}

// static
Process::~Process() = default;

ProcessHandle::ProcessHandle() : mProcess(nullptr) {}

ProcessHandle::ProcessHandle(Process *process) : mProcess(process) {}

ProcessHandle::ProcessHandle(const std::vector<const char *> &args,
                             ProcessOutputCapture captureOutput)
    : mProcess(LaunchProcess(args, captureOutput))
{}

ProcessHandle::~ProcessHandle()
{
    reset();
}

ProcessHandle::ProcessHandle(ProcessHandle &&other) : mProcess(other.mProcess)
{
    other.mProcess = nullptr;
}

ProcessHandle &ProcessHandle::operator=(ProcessHandle &&rhs)
{
    std::swap(mProcess, rhs.mProcess);
    return *this;
}

void ProcessHandle::reset()
{
    if (mProcess)
    {
        delete mProcess;
        mProcess = nullptr;
    }
}

bool ParseIntArgWithHandling(const char *flag,
                             int *argc,
                             char **argv,
                             int argIndex,
                             int *valueOut,
                             ArgHandling handling)
{
    const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
    if (!value)
    {
        return false;
    }

    char *end            = nullptr;
    const long longValue = ANGLE_UNSAFE_TODO(strtol(value, &end, 10));

    if (*end != '\0')
    {
        printf("Error parsing integer flag value.\n");
        exit(EXIT_FAILURE);
    }

    if (longValue == LONG_MAX || longValue == LONG_MIN || static_cast<int>(longValue) != longValue)
    {
        printf("Overflow when parsing integer flag value.\n");
        exit(EXIT_FAILURE);
    }

    *valueOut = static_cast<int>(longValue);
    // Note: return value is always false with ArgHandling::Preserve handling
    return handling == ArgHandling::Delete;
}

bool ParseIntArg(const char *flag, int *argc, char **argv, int argIndex, int *valueOut)
{
    return ParseIntArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
}

bool ParseFlag(const char *flag, int *argc, char **argv, int argIndex, bool *flagOut)
{
    if (ANGLE_UNSAFE_TODO(strcmp(flag, argv[argIndex])) == 0)
    {
        *flagOut = true;
        DeleteArg(argc, argv, argIndex);
        return true;
    }
    return false;
}

bool ParseStringArgWithHandling(const char *flag,
                                int *argc,
                                char **argv,
                                int argIndex,
                                std::string *valueOut,
                                ArgHandling handling)
{
    const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
    if (!value)
    {
        return false;
    }

    *valueOut = value;
    return handling == ArgHandling::Delete;
}

bool ParseStringArg(const char *flag, int *argc, char **argv, int argIndex, std::string *valueOut)
{
    return ParseStringArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
}

bool ParseCStringArgWithHandling(const char *flag,
                                 int *argc,
                                 char **argv,
                                 int argIndex,
                                 const char **valueOut,
                                 ArgHandling handling)
{
    const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
    if (!value)
    {
        return false;
    }

    *valueOut = value;
    // Note: return value is always false with ArgHandling::Preserve handling
    return handling == ArgHandling::Delete;
}

bool ParseCStringArg(const char *flag, int *argc, char **argv, int argIndex, const char **valueOut)
{
    return ParseCStringArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
}

void AddArg(int *argc, char **argv, const char *arg)
{
    // This unsafe const_cast is necessary to work around gtest limitations.
    ANGLE_UNSAFE_TODO(argv[*argc])     = const_cast<char *>(arg);
    ANGLE_UNSAFE_TODO(argv[*argc + 1]) = nullptr;
    (*argc)++;
}

uint32_t GetPlatformANGLETypeFromArg(const char *useANGLEArg, uint32_t defaultPlatformType)
{
    if (!useANGLEArg)
    {
        return defaultPlatformType;
    }

    for (const DisplayTypeInfo &displayTypeInfo : kDisplayTypes)
    {
        if (ANGLE_UNSAFE_TODO(strcmp(displayTypeInfo.first, useANGLEArg)) == 0)
        {
            std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl;
            return displayTypeInfo.second;
        }
    }

    std::cout << "Unknown ANGLE back-end API: " << useANGLEArg << std::endl;
    exit(EXIT_FAILURE);
}

uint32_t GetANGLEDeviceTypeFromArg(const char *useANGLEArg, uint32_t defaultDeviceType)
{
    if (useANGLEArg)
    {
        if (ANGLE_UNSAFE_TODO(strcmp(useANGLEArg, "swiftshader")) == 0)
        {
            return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
        }
        if (ANGLE_UNSAFE_TODO(strstr(useANGLEArg, "null")) != 0)
        {
            return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
        }
    }
    return defaultDeviceType;
}
}  // namespace angle
