//
// 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.
//
// Feature.h: Definition of structs to hold feature/workaround information.
//

#ifndef ANGLE_PLATFORM_FEATURE_H_
#define ANGLE_PLATFORM_FEATURE_H_

#include <map>
#include <string>
#include <vector>

#define ANGLE_FEATURE_CONDITION(set, feature, cond)     \
    do                                                  \
    {                                                   \
        set->feature.enabled   = cond;                  \
        set->feature.condition = ANGLE_STRINGIFY(cond); \
    } while (0)

namespace angle
{

enum class FeatureCategory
{
    FrontendWorkarounds,
    OpenGLWorkarounds,
    D3DWorkarounds,
    D3DCompilerWorkarounds,
    VulkanWorkarounds,
    VulkanFeatures,
    MetalFeatures,
};

constexpr char kFeatureCategoryFrontendWorkarounds[]    = "Frontend workarounds";
constexpr char kFeatureCategoryOpenGLWorkarounds[]      = "OpenGL workarounds";
constexpr char kFeatureCategoryD3DWorkarounds[]         = "D3D workarounds";
constexpr char kFeatureCategoryD3DCompilerWorkarounds[] = "D3D compiler workarounds";
constexpr char kFeatureCategoryVulkanWorkarounds[]      = "Vulkan workarounds";
constexpr char kFeatureCategoryVulkanFeatures[]         = "Vulkan features";
constexpr char kFeatureCategoryMetalFeatures[]          = "Metal features";
constexpr char kFeatureCategoryUnknown[]                = "Unknown";

inline const char *FeatureCategoryToString(const FeatureCategory &fc)
{
    switch (fc)
    {
        case FeatureCategory::FrontendWorkarounds:
            return kFeatureCategoryFrontendWorkarounds;
            break;

        case FeatureCategory::OpenGLWorkarounds:
            return kFeatureCategoryOpenGLWorkarounds;
            break;

        case FeatureCategory::D3DWorkarounds:
            return kFeatureCategoryD3DWorkarounds;
            break;

        case FeatureCategory::D3DCompilerWorkarounds:
            return kFeatureCategoryD3DCompilerWorkarounds;
            break;

        case FeatureCategory::VulkanWorkarounds:
            return kFeatureCategoryVulkanWorkarounds;
            break;

        case FeatureCategory::VulkanFeatures:
            return kFeatureCategoryVulkanFeatures;
            break;

        case FeatureCategory::MetalFeatures:
            return kFeatureCategoryMetalFeatures;
            break;

        default:
            return kFeatureCategoryUnknown;
            break;
    }
}

constexpr char kFeatureStatusEnabled[]  = "enabled";
constexpr char kFeatureStatusDisabled[] = "disabled";

inline const char *FeatureStatusToString(const bool &status)
{
    if (status)
    {
        return kFeatureStatusEnabled;
    }
    return kFeatureStatusDisabled;
}

struct Feature;

using FeatureMap  = std::map<std::string, Feature *>;
using FeatureList = std::vector<const Feature *>;

struct Feature
{
    Feature(const Feature &other);
    Feature(const char *name,
            const FeatureCategory &category,
            const char *description,
            FeatureMap *const mapPtr,
            const char *bug);
    ~Feature();

    // The name of the workaround, lowercase, camel_case
    const char *const name;

    // The category that the workaround belongs to. Eg. "Vulkan workarounds"
    const FeatureCategory category;

    // A short description to be read by the user.
    const char *const description;

    // A link to the bug, if any
    const char *const bug;

    // Whether the workaround is enabled or not. Determined by heuristics like vendor ID and
    // version, but may be overriden to any value.
    bool enabled = false;

    // A stingified version of the condition used to set 'enabled'. ie "IsNvidia() && IsApple()"
    const char *condition;
};

inline Feature::Feature(const Feature &other) = default;
inline Feature::Feature(const char *name,
                        const FeatureCategory &category,
                        const char *description,
                        FeatureMap *const mapPtr,
                        const char *bug = "")
    : name(name),
      category(category),
      description(description),
      bug(bug),
      enabled(false),
      condition(nullptr)
{
    if (mapPtr != nullptr)
    {
        (*mapPtr)[std::string(name)] = this;
    }
}

inline Feature::~Feature() = default;

struct FeatureSetBase
{
  public:
    FeatureSetBase();
    ~FeatureSetBase();

  private:
    // Non-copyable
    FeatureSetBase(const FeatureSetBase &other) = delete;
    FeatureSetBase &operator=(const FeatureSetBase &other) = delete;

  protected:
    FeatureMap members = FeatureMap();

  public:
    void overrideFeatures(const std::vector<std::string> &feature_names, const bool enabled)
    {
        for (const std::string &name : feature_names)
        {
            if (members.find(name) != members.end())
            {
                members[name]->enabled = enabled;
            }
        }
    }

    void populateFeatureList(FeatureList *features) const
    {
        for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++)
        {
            features->push_back(it->second);
        }
    }
};

inline FeatureSetBase::FeatureSetBase()  = default;
inline FeatureSetBase::~FeatureSetBase() = default;

}  // namespace angle

#endif  // ANGLE_PLATFORM_WORKAROUND_H_
