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

// feature_support_util.cpp: Helps client APIs make decisions based on rules
// data files.  For example, the Android EGL loader uses this library to
// determine whether to use ANGLE or a native GLES driver.

#include "feature_support_util.h"
#include <json/json.h>
#include <string.h>
#include "common/platform.h"
#if defined(ANGLE_PLATFORM_ANDROID)
#    include <android/log.h>
#    include <unistd.h>
#endif
#include <fstream>
#include <ios>
#include <list>
#include <memory>
#include <sstream>
#include <utility>
#include <vector>
#include "../gpu_info_util/SystemInfo.h"

namespace angle
{

#if defined(ANGLE_PLATFORM_ANDROID)
// Define ANGLE_FEATURE_UTIL_LOG_VERBOSE if you want VERBOSE to output
// ANGLE_FEATURE_UTIL_LOG_VERBOSE is automatically defined when is_debug = true

#    define ERR(...) __android_log_print(ANDROID_LOG_ERROR, "ANGLE", __VA_ARGS__)
#    define WARN(...) __android_log_print(ANDROID_LOG_WARN, "ANGLE", __VA_ARGS__)
#    define INFO(...) __android_log_print(ANDROID_LOG_INFO, "ANGLE", __VA_ARGS__)
#    define DEBUG(...) __android_log_print(ANDROID_LOG_DEBUG, "ANGLE", __VA_ARGS__)
#    ifdef ANGLE_FEATURE_UTIL_LOG_VERBOSE
#        define VERBOSE(...) __android_log_print(ANDROID_LOG_VERBOSE, "ANGLE", __VA_ARGS__)
#    else
#        define VERBOSE(...) ((void)0)
#    endif
#else  // defined(ANDROID)
#    define ERR(...) printf(__VA_ARGS__)
#    define WARN(...) printf(__VA_ARGS__)
#    define INFO(...) printf(__VA_ARGS__)
#    define DEBUG(...) printf(__VA_ARGS__)
// Uncomment for debugging.
//#    define VERBOSE(...) printf(__VA_ARGS__)
#    define VERBOSE(...)
#endif  // defined(ANDROID)

// JSON values are generally composed of either:
//  - Objects, which are a set of comma-separated string:value pairs (note the recursive nature)
//  - Arrays, which are a set of comma-separated values.
// We'll call the string in a string:value pair the "identifier".  These identifiers are defined
// below, as follows:

// The JSON identifier for the top-level set of rules.  This is an object, the value of which is an
// array of rules.  The rules will be processed in order.  If a rule matches, the rule's version of
// the answer (true or false) becomes the new answer.  After all rules are processed, the
// most-recent answer is the final answer.
constexpr char kJsonRules[] = "Rules";
// The JSON identifier for a given rule.  A rule is an object, the first string:value pair is this
// identifier (i.e. "Rule") as the string and the value is a user-firendly description of the rule:
constexpr char kJsonRule[] = "Rule";
// Within a rule, the JSON identifier for the answer--whether or not to use ANGLE.  The value is a
// boolean (i.e. true or false).
constexpr char kJsonUseANGLE[] = "UseANGLE";

// Within a rule, the JSON identifier for describing one or more applications.  The value is an
// array of objects, each object of which can specify attributes of an application.
constexpr char kJsonApplications[] = "Applications";
// Within an object that describes the attributes of an application, the JSON identifier for the
// name of the application (e.g. "com.google.maps").  The value is a string.  If any other
// attributes will be specified, this must be the first attribute specified in the object.
constexpr char kJsonAppName[] = "AppName";

// Within a rule, the JSON identifier for describing one or more devices.  The value is an
// array of objects, each object of which can specify attributes of a device.
constexpr char kJsonDevices[] = "Devices";
// Within an object that describes the attributes of a device, the JSON identifier for the
// manufacturer of the device.  The value is a string.  If any other non-GPU attributes will be
// specified, this must be the first attribute specified in the object.
constexpr char kJsonManufacturer[] = "Manufacturer";
// Within an object that describes the attributes of a device, the JSON identifier for the
// model of the device.  The value is a string.
constexpr char kJsonModel[] = "Model";

// Within an object that describes the attributes of a device, the JSON identifier for describing
// one or more GPUs/drivers used in the device.  The value is an
// array of objects, each object of which can specify attributes of a GPU and its driver.
constexpr char kJsonGPUs[] = "GPUs";
// Within an object that describes the attributes of a GPU and driver, the JSON identifier for the
// vendor of the device/driver.  The value is a string.  If any other attributes will be specified,
// this must be the first attribute specified in the object.
constexpr char kJsonVendor[] = "Vendor";
// Within an object that describes the attributes of a GPU and driver, the JSON identifier for the
// deviceId of the device.  The value is an unsigned integer.  If the driver version will be
// specified, this must preceded the version attributes specified in the object.
constexpr char kJsonDeviceId[] = "DeviceId";

// Within an object that describes the attributes of either an application or a GPU, the JSON
// identifier for the major version of that application or GPU driver.  The value is a positive
// integer number.  Not specifying a major version implies a wildcard for all values of a version.
constexpr char kJsonVerMajor[] = "VerMajor";
// Within an object that describes the attributes of either an application or a GPU, the JSON
// identifier for the minor version of that application or GPU driver.  The value is a positive
// integer number.  In order to specify a minor version, it must be specified immediately after the
// major number associated with it.  Not specifying a minor version implies a wildcard for the
// minor, subminor, and patch values of a version.
constexpr char kJsonVerMinor[] = "VerMinor";
// Within an object that describes the attributes of either an application or a GPU, the JSON
// identifier for the subminor version of that application or GPU driver.  The value is a positive
// integer number.  In order to specify a subminor version, it must be specified immediately after
// the minor number associated with it.  Not specifying a subminor version implies a wildcard for
// the subminor and patch values of a version.
constexpr char kJsonVerSubMinor[] = "VerSubMinor";
// Within an object that describes the attributes of either an application or a GPU, the JSON
// identifier for the patch version of that application or GPU driver.  The value is a positive
// integer number.  In order to specify a patch version, it must be specified immediately after the
// subminor number associated with it.  Not specifying a patch version implies a wildcard for the
// patch value of a version.
constexpr char kJsonVerPatch[] = "VerPatch";

// This encapsulates a std::string.  The default constructor (not given a string) assumes that this
// is a wildcard (i.e. will match all other StringPart objects).
class StringPart
{
  public:
    StringPart() = default;
    explicit StringPart(const std::string part) : mPart(part), mWildcard(false) {}
    ~StringPart() = default;

    static StringPart FromJson(const Json::Value &parent, const char *key)
    {
        if (parent.isMember(key) && parent[key].isString())
        {
            return StringPart(parent[key].asString());
        }
        return {};
    }

    bool match(const StringPart &toCheck) const
    {
        return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart));
    }

  public:
    std::string mPart;
    bool mWildcard = true;
};

// This encapsulates a 32-bit unsigned integer.  The default constructor (not given a number)
// assumes that this is a wildcard (i.e. will match all other IntegerPart objects).
class IntegerPart
{
  public:
    IntegerPart() = default;
    explicit IntegerPart(uint32_t part) : mPart(part), mWildcard(false) {}
    ~IntegerPart() = default;

    static IntegerPart FromJson(const Json::Value &parent, const char *key)
    {
        if (parent.isMember(key) && parent[key].isInt())
        {
            return IntegerPart(parent[key].asInt());
        }
        return {};
    }

    bool match(const IntegerPart &toCheck) const
    {
        return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart));
    }

  public:
    uint32_t mPart = 0;
    bool mWildcard = true;
};

// This encapsulates a list of other classes, each of which will have a match() and logItem()
// method.  The common constructor (given a type, but not any list items) assumes that this is
// a wildcard (i.e. will match all other ListOf<t> objects).
template <class T>
class ListOf
{
  public:
    explicit ListOf(const std::string listType) : mWildcard(true), mListType(listType) {}
    ~ListOf() { mList.clear(); }
    void addItem(T &&toAdd)
    {
        mList.push_back(std::move(toAdd));
        mWildcard = false;
    }
    bool match(const T &toCheck) const
    {
        VERBOSE("\t\t Matching ListOf<%s> against item:\n", mListType.c_str());
        if (mWildcard || toCheck.mWildcard)
        {
            VERBOSE("\t\t\t Successful match due to wildcard.\n");
            return true;
        }
        for (const T &it : mList)
        {
            if (it.match(toCheck))
            {
                VERBOSE("\t\t\t Successful match due to list item match.\n");
                return true;
            }
        }
        VERBOSE("\t\t\t Failed to match.\n");
        return false;
    }
    bool match(const ListOf<T> &toCheck) const
    {
        VERBOSE("\t\t Matching ListOf<%s>:\n", mListType.c_str());
        if (mWildcard || toCheck.mWildcard)
        {
            VERBOSE("\t\t\t Successful match due to wildcard.\n");
            return true;
        }
        // If we make it to here, both this and toCheck have at least one item in their mList.
        for (const T &it : toCheck.mList)
        {
            if (match(it))
            {
                VERBOSE("\t\t\t Successful match due to list item match.\n");
                return true;
            }
        }
        VERBOSE("\t\t\t Failed to match list.\n");
        return false;
    }
    void logListOf(const std::string prefix, const std::string name) const
    {
        if (mWildcard)
        {
            VERBOSE("%sListOf%s is wildcarded to always match\n", prefix.c_str(), name.c_str());
        }
        else
        {
            VERBOSE("%sListOf%s has %d item(s):\n", prefix.c_str(), name.c_str(),
                    static_cast<int>(mList.size()));
            for (auto &it : mList)
            {
                it.logItem();
            }
        }
    }

    bool mWildcard;

  private:
    std::string mListType;
    std::vector<T> mList;
};

// This encapsulates up-to four 32-bit unsigned integers, that represent a potentially-complex
// version number.  The default constructor (not given any numbers) assumes that this is a wildcard
// (i.e. will match all other Version objects).  Each part of a Version is stored in an IntegerPart
// class, and so may be wildcarded as well.
class Version
{
  public:
    Version(uint32_t major, uint32_t minor, uint32_t subminor, uint32_t patch)
        : mMajor(major), mMinor(minor), mSubminor(subminor), mPatch(patch)
    {}

    Version()                = default;
    Version(const Version &) = default;
    Version(Version &&)      = default;
    Version &operator=(const Version &) = default;
    Version &operator=(Version &&) = default;
    ~Version()                     = default;

    static Version FromJson(const Json::Value &jObject)
    {
        Version version;
        version.mMajor = IntegerPart::FromJson(jObject, kJsonVerMajor);
        if (version.mMajor.mWildcard)
        {
            return version;
        }
        // Revision fields are only checked if their parent version field
        // is set.
        version.mMinor = IntegerPart::FromJson(jObject, kJsonVerMinor);
        if (version.mMinor.mWildcard)
        {
            return version;
        }

        version.mSubminor = IntegerPart::FromJson(jObject, kJsonVerSubMinor);
        if (version.mSubminor.mWildcard)
        {
            return version;
        }

        version.mPatch = IntegerPart::FromJson(jObject, kJsonVerPatch);
        return version;
    }

    bool match(const Version &toCheck) const
    {
        VERBOSE("\t\t\t Matching Version %s against %s\n", getString().c_str(),
                toCheck.getString().c_str());
        return (isWildcard() || toCheck.isWildcard() ||
                (mMajor.match(toCheck.mMajor) && mMinor.match(toCheck.mMinor) &&
                 mSubminor.match(toCheck.mSubminor) && mPatch.match(toCheck.mPatch)));
    }

    std::string getString() const
    {
        if (mMajor.mWildcard)
        {
            return "*";
        }

        std::ostringstream ss;
        ss << mMajor.mPart;
        // Must at least have a major version:
        if (!mMinor.mWildcard)
        {
            ss << "." << mMinor.mPart;
            if (!mSubminor.mWildcard)
            {
                ss << "." << mSubminor.mPart;

                if (!mPatch.mWildcard)
                {
                    ss << "." << mPatch.mPart;
                }
            }
        }
        if (mPatch.mWildcard)
        {
            ss << ".*";
        }
        return ss.str();
    }

    bool isWildcard() const { return mMajor.mWildcard; }

  public:
    IntegerPart mMajor;
    IntegerPart mMinor;
    IntegerPart mSubminor;
    IntegerPart mPatch;
};

// This encapsulates an application, and potentially the application's Version.  The default
// constructor (not given any values) assumes that this is a wildcard (i.e. will match all
// other Application objects).  Each part of an Application is stored in a class that may
// also be wildcarded.
class Application
{
  public:
    Application(StringPart name, Version version = {})
        : mName(name), mVersion(version), mWildcard(false)
    {}
    Application()  = default;
    ~Application() = default;

    static bool FromJson(const Json::Value &jObject, Application *out)
    {
        // If an application is listed, the application's name is required:
        auto name = StringPart::FromJson(jObject, kJsonAppName);
        if (name.mWildcard)
        {
            return false;
        }
        auto version = Version::FromJson(jObject);
        *out         = Application{std::move(name), std::move(version)};
        return true;
    }

    bool match(const Application &toCheck) const
    {
        return (mWildcard || toCheck.mWildcard ||
                (toCheck.mName.match(mName) && toCheck.mVersion.match(mVersion)));
    }
    void logItem() const
    {
        if (mWildcard)
        {
            VERBOSE("      Wildcard (i.e. will match all applications)\n");
        }
        else if (!mVersion.isWildcard())
        {
            VERBOSE("      Application \"%s\" (version: %s)\n", mName.mPart.c_str(),
                    mVersion.getString().c_str());
        }
        else
        {
            VERBOSE("      Application \"%s\"\n", mName.mPart.c_str());
        }
    }

  public:
    StringPart mName;
    Version mVersion;
    bool mWildcard = true;
};

// This encapsulates a GPU and its driver.  The default constructor (not given any values) assumes
// that this is a wildcard (i.e. will match all other GPU objects).  Each part of a GPU is stored
// in a class that may also be wildcarded.
class GPU
{
  public:
    GPU(StringPart vendor, IntegerPart deviceId, Version version)
        : mVendor(std::move(vendor)),
          mDeviceId(std::move(deviceId)),
          mVersion(version),
          mWildcard(false)
    {}
    GPU(std::string vendor, uint32_t deviceId, Version version)
        : GPU(StringPart(std::move(vendor)), IntegerPart(deviceId), std::move(version))
    {}
    GPU()  = default;
    ~GPU() = default;
    bool match(const GPU &toCheck) const
    {
        VERBOSE("\t\t Matching %s \n\t\t  against %s\n", toString().c_str(),
                toCheck.toString().c_str());
        return (mWildcard || toCheck.mWildcard ||
                (toCheck.mVendor.match(mVendor) && toCheck.mDeviceId.match(mDeviceId) &&
                 toCheck.mVersion.match(mVersion)));
    }

    // Returns true if out is set to a valid GPU instance.
    static bool CreateGpuFromJson(const Json::Value &jObject, GPU *out)
    {
        // If a GPU is listed, the vendor name is required:
        auto vendor = StringPart::FromJson(jObject, kJsonVendor);
        if (vendor.mWildcard)
        {
            WARN("Asked to parse a GPU, but no vendor found.\n");
            return false;
        }

        auto deviceId = IntegerPart::FromJson(jObject, kJsonDeviceId);
        auto version  = Version::FromJson(jObject);
        *out          = GPU{std::move(vendor), std::move(deviceId), std::move(version)};
        return true;
    }

    std::string toString() const
    {
        if (mWildcard)
        {
            return std::string("Wildcard (i.e. will match all GPUs)");
        }

        std::ostringstream ss;
        ss << "GPU vendor: " << mVendor.mPart;
        if (!mDeviceId.mWildcard)
        {
            ss << ", deviceId: " << std::hex << mDeviceId.mPart;
        }
        ss << ", version: " << mVersion.getString();
        return ss.str();
    }

    void logItem() const { VERBOSE("\t     %s\n", toString().c_str()); }

  public:
    StringPart mVendor;
    IntegerPart mDeviceId;
    Version mVersion;
    bool mWildcard = true;
};

// This encapsulates a device, and potentially the device's model and/or a list of GPUs/drivers
// associated with the Device.  The default constructor (not given any values) assumes that this is
// a wildcard (i.e. will match all other Device objects).  Each part of a Device is stored in a
// class that may also be wildcarded.
class Device
{
  public:
    Device(StringPart manufacturer, StringPart model)
        : mManufacturer(std::move(manufacturer)),
          mModel(std::move(model)),
          mGpuList("GPU"),
          mWildcard(false)
    {}
    Device() : mGpuList("GPU") {}
    ~Device() = default;

    static Device FromJson(const Json::Value &jObject)
    {
        auto manufacturer = StringPart::FromJson(jObject, kJsonManufacturer);
        if (!manufacturer.mWildcard)
        {
            // We don't let a model be specified without also specifying a manufacturer:
            auto model = StringPart::FromJson(jObject, kJsonModel);
            return Device(std::move(manufacturer), std::move(model));
        }
        // This case is not treated as an error because a rule may wish to only call out one or
        // more GPUs, but not any specific manufacturer (e.g. for any manufacturer's device
        // that uses a GPU from Vendor-A, with DeviceID-Foo, and with driver version 1.2.3.4):
        return Device();
    }

    void addGPU(GPU &&gpu) { mGpuList.addItem(std::move(gpu)); }
    bool match(const Device &toCheck) const
    {
        // GPU lists must always match, even when wildcards are used.
        VERBOSE("\t   Checking ListOf<GPU>:\n");
        if (!mGpuList.match(toCheck.mGpuList))
        {
            VERBOSE("\t Failed to match due to mismatched GPU list.\n");
            return false;
        }
        if (mWildcard || toCheck.mWildcard)
        {
            VERBOSE("\t  Matching due to wildcard.\n");
            return true;
        }
        if (toCheck.mManufacturer.match(mManufacturer) && toCheck.mModel.match(mModel))
        {
            VERBOSE("\t  Matching due to manufacturer and model match.\n");
            return true;
        }
        return false;
    }
    void logItem() const
    {
        if (mWildcard)
        {
            if (mGpuList.mWildcard)
            {
                VERBOSE("      Wildcard (i.e. will match all devices)\n");
                return;
            }
            else
            {
                VERBOSE(
                    "      Device with any manufacturer and model"
                    ", and with the following GPUs:\n");
            }
        }
        else
        {
            if (!mModel.mWildcard)
            {
                VERBOSE(
                    "      Device manufacturer: \"%s\" and model \"%s\""
                    ", and with the following GPUs:\n",
                    mManufacturer.mPart.c_str(), mModel.mPart.c_str());
            }
            else
            {
                VERBOSE(
                    "      Device manufacturer: \"%s\""
                    ", and with the following GPUs:\n",
                    mManufacturer.mPart.c_str());
            }
        }
        mGpuList.logListOf("        ", "GPUs");
    }

  public:
    StringPart mManufacturer;
    StringPart mModel;
    ListOf<GPU> mGpuList;
    bool mWildcard = true;
};

// This encapsulates a particular scenario to check against the rules.  A Scenario is similar to a
// Rule, except that a Rule has an answer and potentially many wildcards, and a Scenario is the
// fully-specified combination of an Application and a Device that is proposed to be run with
// ANGLE.  It is compared with the list of Rules.
class Scenario
{
  public:
    Scenario(const char *appName, const char *deviceMfr, const char *deviceModel)
        : mApplication(Application(StringPart(appName))),
          mDevice(Device(StringPart(deviceMfr), StringPart(deviceModel)))
    {}
    ~Scenario() = default;
    void logScenario()
    {
        VERBOSE("  Scenario to compare against the rules:\n");
        VERBOSE("    Application:\n");
        mApplication.logItem();
        VERBOSE("    Device:\n");
        mDevice.logItem();
    }

  public:
    Application mApplication;
    Device mDevice;
};

// This encapsulates a Rule that provides an answer based on whether a particular Scenario matches
// the Rule.  A Rule always has an answer, but can potentially wildcard every item in it (i.e.
// match every scenario).
class Rule
{
  public:
    Rule(const std::string description, bool useANGLE)
        : mDescription(description),
          mAppList("Application"),
          mDevList("Device"),
          mUseANGLE(useANGLE)
    {}
    ~Rule() = default;
    void addApp(Application &&app) { mAppList.addItem(std::move(app)); }
    void addDevice(Device &&dev) { mDevList.addItem(std::move(dev)); }
    bool match(const Scenario &toCheck) const
    {
        VERBOSE("    Matching rule \"%s\" against scenario:\n", mDescription.c_str());
        if (!mAppList.match(toCheck.mApplication))
        {
            VERBOSE("\tFailed to match rule due to mismatched application.\n");
            return false;
        }
        if (!mDevList.match(toCheck.mDevice))
        {
            VERBOSE("\tFailed to match rule due to mismatched device.\n");
            return false;
        }
        VERBOSE("\tSuccessfully matched rule.");
        return true;
    }
    bool getUseANGLE() const { return mUseANGLE; }
    void logRule() const
    {
        VERBOSE("  Rule: \"%s\" %s ANGLE\n", mDescription.c_str(),
                mUseANGLE ? "enables" : "disables");
        mAppList.logListOf("    ", "Applications");
        mDevList.logListOf("    ", "Devices");
    }

    std::string mDescription;
    ListOf<Application> mAppList;
    ListOf<Device> mDevList;
    bool mUseANGLE;
};

// This encapsulates a list of Rules that Scenarios are matched against.  A Scenario is compared
// with each Rule, in order.  Any time a Scenario matches a Rule, the current answer is overridden
// with the answer of the matched Rule.
class RuleList
{
  public:
    RuleList() {}
    ~RuleList() { mRuleList.clear(); }

    static RuleList *ReadRulesFromJsonString(const std::string jsonFileContents)
    {
        RuleList *rules = new RuleList;

        // Open the file and start parsing it:
        Json::CharReaderBuilder builder;
        // Json::CharReaderBuilder::strictMode(&builder.settings_);
        std::unique_ptr<Json::CharReader> reader(builder.newCharReader());

        Json::Value jTopLevelObject;
        std::string errorMessage;
        const bool succeeded = reader->parse(&*jsonFileContents.begin(), &*jsonFileContents.end(),
                                             &jTopLevelObject, &errorMessage);
        if (!succeeded)
        {
            VERBOSE("Failed to parse rules from json file. Error: %s\n", errorMessage.c_str());
            return nullptr;
        }

        for (const auto &jRule : jTopLevelObject[kJsonRules])
        {
            std::string ruleDescription = jRule[kJsonRule].asString();
            bool useANGLE               = jRule[kJsonUseANGLE].asBool();
            Rule newRule(std::move(ruleDescription), useANGLE);

            for (const auto &jApp : jRule[kJsonApplications])
            {
                Application app;
                if (Application::FromJson(jApp, &app))
                {
                    newRule.addApp(std::move(app));
                }
            }

            for (const auto &jDev : jRule[kJsonDevices])
            {
                Device newDev = Device::FromJson(jDev);
                for (const auto &jGPU : jDev[kJsonGPUs])
                {
                    GPU newGPU;
                    if (GPU::CreateGpuFromJson(jGPU, &newGPU))
                    {
                        newDev.addGPU(std::move(newGPU));
                    }
                }
                newRule.addDevice(std::move(newDev));
            }

            rules->addRule(std::move(newRule));
        }

        // Make sure there is at least one, default rule.  If not, add it here:
        if (rules->mRuleList.empty())
        {
            Rule defaultRule("Default Rule", false);
            rules->addRule(std::move(defaultRule));
        }
        return rules;
    }

    void addRule(Rule &&rule) { mRuleList.push_back(std::move(rule)); }
    bool getUseANGLE(const Scenario &toCheck)
    {
        // Initialize useANGLE to the system-wide default (that should be set in the default
        // rule, but just in case, set it here too):
        bool useANGLE = false;
        VERBOSE("Checking scenario against %d ANGLE-for-Android rules:\n",
                static_cast<int>(mRuleList.size()));

        for (const Rule &rule : mRuleList)
        {
            VERBOSE("  Checking Rule: \"%s\" (to see whether there's a match)\n",
                    rule.mDescription.c_str());
            if (rule.match(toCheck))
            {
                VERBOSE("  -> Rule matches.  Updating useANGLE to %s.\n",
                        rule.getUseANGLE() ? "true" : "false");
                // The ANGLE rules are ordered from least to greatest specificity, meaning that
                // the last rule with a match should dictate whether or not ANGLE should be
                // recommended for use.
                useANGLE = rule.getUseANGLE();
            }
            else
            {
                VERBOSE("  -> Rule doesn't match.\n");
            }
        }
        return useANGLE;
    }
    void logRules()
    {
        VERBOSE("Showing %d ANGLE-for-Android rules:\n", static_cast<int>(mRuleList.size()));
        for (const Rule &rule : mRuleList)
        {
            rule.logRule();
        }
    }

  public:
    std::vector<Rule> mRuleList;
};

}  // namespace angle

extern "C" {

using namespace angle;

// This function is part of the version-2 API:
ANGLE_EXPORT bool ANGLEGetFeatureSupportUtilAPIVersion(unsigned int *versionToUse)
{
    if (!versionToUse || (*versionToUse < kFeatureVersion_LowestSupported))
    {
        // The versionToUse is either nullptr or is less than the lowest version supported, which
        // is an error.
        return false;
    }
    if (*versionToUse > kFeatureVersion_HighestSupported)
    {
        // The versionToUse is greater than the highest version supported; change it to the
        // highest version supported (caller will decide if it can use that version).
        *versionToUse = kFeatureVersion_HighestSupported;
    }
    return true;
}

// This function is part of the version-2 API:
ANGLE_EXPORT bool ANGLEAndroidParseRulesString(const char *rulesString,
                                               RulesHandle *rulesHandle,
                                               int *rulesVersion)
{
    if (!rulesString || !rulesHandle || !rulesVersion)
    {
        return false;
    }

    std::string rulesFileContents = rulesString;
    RuleList *rules               = RuleList::ReadRulesFromJsonString(rulesFileContents);
    if (!rules)
    {
        return false;
    }

    rules->logRules();

    *rulesHandle  = rules;
    *rulesVersion = 0;
    return true;
}

// This function is part of the version-2 API:
ANGLE_EXPORT bool ANGLEGetSystemInfo(SystemInfoHandle *systemInfoHandle)
{
    if (!systemInfoHandle)
    {
        return false;
    }

    // TODO (http://anglebug.com/3036): Restore the real code
    angle::SystemInfo *systemInfo = new angle::SystemInfo;
    systemInfo->gpus.resize(1);
    GPUDeviceInfo &gpu = systemInfo->gpus[0];
    gpu.vendorId       = 0xFEFEFEFE;
    gpu.deviceId       = 0xFEEEFEEE;
    gpu.driverVendor   = "Foo";
    gpu.driverVersion  = "1.2.3.4";

    *systemInfoHandle = systemInfo;
    return true;
}

// This function is part of the version-2 API:
ANGLE_EXPORT bool ANGLEAddDeviceInfoToSystemInfo(const char *deviceMfr,
                                                 const char *deviceModel,
                                                 SystemInfoHandle systemInfoHandle)
{
    angle::SystemInfo *systemInfo = static_cast<angle::SystemInfo *>(systemInfoHandle);
    if (!deviceMfr || !deviceModel || !systemInfo)
    {
        return false;
    }

    systemInfo->machineManufacturer = deviceMfr;
    systemInfo->machineModelName    = deviceModel;
    return true;
}

// This function is part of the version-2 API:
ANGLE_EXPORT bool ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle,
                                                  int rulesVersion,
                                                  const SystemInfoHandle systemInfoHandle,
                                                  const char *appName)
{
    RuleList *rules               = static_cast<RuleList *>(rulesHandle);
    angle::SystemInfo *systemInfo = static_cast<angle::SystemInfo *>(systemInfoHandle);
    if (!rules || !systemInfo || !appName || (systemInfo->gpus.size() != 1))
    {
        return false;
    }

    Scenario scenario(appName, systemInfo->machineManufacturer.c_str(),
                      systemInfo->machineModelName.c_str());
    Version gpuDriverVersion(systemInfo->gpus[0].detailedDriverVersion.major,
                             systemInfo->gpus[0].detailedDriverVersion.minor,
                             systemInfo->gpus[0].detailedDriverVersion.subMinor,
                             systemInfo->gpus[0].detailedDriverVersion.patch);
    GPU gpuDriver(systemInfo->gpus[0].driverVendor, systemInfo->gpus[0].deviceId,
                  std::move(gpuDriverVersion));
    scenario.mDevice.addGPU(std::move(gpuDriver));
    scenario.logScenario();

    bool rtn = rules->getUseANGLE(std::move(scenario));
    VERBOSE("Application \"%s\" should %s ANGLE.\n", appName, rtn ? "use" : "NOT use");

    return rtn;
}

// This function is part of the version-2 API:
ANGLE_EXPORT void ANGLEFreeRulesHandle(const RulesHandle rulesHandle)
{
    RuleList *rules = static_cast<RuleList *>(rulesHandle);
    if (rules)
    {
        delete rules;
    }
}

// This function is part of the version-2 API:
ANGLE_EXPORT void ANGLEFreeSystemInfoHandle(const SystemInfoHandle systemInfoHandle)
{
    angle::SystemInfo *systemInfo = static_cast<angle::SystemInfo *>(systemInfoHandle);
    if (systemInfo)
    {
        delete systemInfo;
    }
}

}  // extern "C"
