//
// Copyright 2022 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.
//

#include "common/apple_platform_utils.h"

#include "common/debug.h"
#include "common/system_utils.h"
#include "common/unsafe_buffers.h"

#include <Foundation/Foundation.h>
#include <Metal/Metal.h>

namespace angle
{

bool IsMetalRendererAvailable()
{
#if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
    static bool queriedMachineModel    = false;
    static bool machineModelSufficient = true;

    if (!queriedMachineModel)
    {
        queriedMachineModel = true;

        std::string fullMachineModel;
        if (GetMacosMachineModel(&fullMachineModel))
        {
            using MachineModelVersion = std::pair<int32_t, int32_t>;

            std::string name;
            MachineModelVersion version;
            ParseMacMachineModel(fullMachineModel, &name, &version.first, &version.second);

            std::optional<MachineModelVersion> minVersion;
            if (name == "MacBookAir")
            {
                minVersion = {8, 1};  // MacBook Air (Retina, 13-inch, 2018)
            }
            else if (name == "MacBookPro")
            {
                minVersion = {13, 1};  // MacBook Pro (13-inch, 2016)
            }
            else if (name == "MacBook")
            {
                minVersion = {9, 1};  // MacBook (Retina, 12-inch, Early 2016)
            }
            else if (name == "Macmini")
            {
                minVersion = {8, 1};  // Mac mini (2018)
            }
            else if (name == "iMac")
            {
                minVersion = {17, 1};  // iMac (Retina 5K, 27-inch, Late 2015)
            }
            else if (name == "iMacPro")
            {
                minVersion = {1, 1};  // iMac Pro
            }

            if (minVersion.has_value() && version < minVersion.value())
            {
                WARN() << "Disabling Metal because machine model \"" << fullMachineModel
                       << "\" is below the minium supported version.";
                machineModelSufficient = false;
            }
        }
    }

    if (!machineModelSufficient)
    {
        ASSERT(queriedMachineModel);
        return false;
    }
#endif

#if defined(ANGLE_PLATFORM_MACOS) && defined(__aarch64__)
    NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
    if (systemVersion.majorVersion == 15 && systemVersion.minorVersion == 0)
    {
        // On ARM64 MacOS 15.0.x, Metal Shader with newLibraryWithSource didn't work,
        // if the executable path contains non-ASCII characters.
        // Bug: https://issues.chromium.org/issues/389559087
        std::string executableName = GetExecutablePath();
        for (char c : executableName)
        {
            if (static_cast<unsigned char>(c) > 127)
            {
                return false;
            }
        }
    }
#endif

    static bool gpuFamilySufficient = []() -> bool {
        ANGLE_APPLE_OBJC_SCOPE
        {
            auto device = [MTLCreateSystemDefaultDevice() ANGLE_APPLE_AUTORELEASE];
            if (!device)
            {
                return false;
            }
#if TARGET_OS_MACCATALYST && __IPHONE_OS_VERSION_MIN_REQUIRED < 160000
            // Devices in family 1, such as MacBookPro11,4, cannot use ANGLE's Metal backend.
            return [device supportsFamily:MTLGPUFamilyMacCatalyst2];
#elif TARGET_OS_MACCATALYST || TARGET_OS_OSX
            // Devices in family 1, such as MacBookPro11,4, cannot use ANGLE's Metal backend.
            return [device supportsFamily:MTLGPUFamilyMac2];
#else
            // Devices starting with A9 onwards are supported. Simulator is supported as per
            // definition that running simulator on Mac Family 1 devices is not supported.
            return true;
#endif
        }
    }();
    return gpuFamilySufficient;
}

#if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
bool GetMacosMachineModel(std::string *outMachineModel)
{
    io_service_t platformExpert = IOServiceGetMatchingService(
        kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice"));

    if (platformExpert == IO_OBJECT_NULL)
    {
        return false;
    }

    CFDataRef modelData = static_cast<CFDataRef>(
        IORegistryEntryCreateCFProperty(platformExpert, CFSTR("model"), kCFAllocatorDefault, 0));
    if (modelData == nullptr)
    {
        IOObjectRelease(platformExpert);
        return false;
    }

    *outMachineModel = reinterpret_cast<const char *>(CFDataGetBytePtr(modelData));

    IOObjectRelease(platformExpert);
    CFRelease(modelData);

    return true;
}

bool ParseMacMachineModel(const std::string &identifier,
                          std::string *type,
                          int32_t *major,
                          int32_t *minor)
{
    size_t numberLoc = identifier.find_first_of("0123456789");
    if (numberLoc == std::string::npos)
    {
        return false;
    }

    size_t commaLoc = identifier.find(',', numberLoc);
    if (commaLoc == std::string::npos || commaLoc >= identifier.size())
    {
        return false;
    }

    const char *numberPtr = &identifier[numberLoc];
    const char *commaPtr  = &identifier[commaLoc + 1];
    char *endPtr          = nullptr;

    int32_t majorTmp = static_cast<int32_t>(ANGLE_UNSAFE_TODO(std::strtol(numberPtr, &endPtr, 10)));
    if (endPtr == numberPtr)
    {
        return false;
    }

    int32_t minorTmp = static_cast<int32_t>(ANGLE_UNSAFE_TODO(std::strtol(commaPtr, &endPtr, 10)));
    if (endPtr == commaPtr)
    {
        return false;
    }

    *major = majorTmp;
    *minor = minorTmp;
    *type  = identifier.substr(0, numberLoc);

    return true;
}
#endif

}  // namespace angle
