/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/sksl/ir/SkSLSetting.h"

#include "include/core/SkTypes.h"
#include "include/private/SkTHash.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLBuiltinTypes.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLLiteral.h"

#include <initializer_list>

namespace SkSL {

namespace {

using CapsLookupTable = SkTHashMap<std::string_view, Setting::CapsPtr>;

static const CapsLookupTable& caps_lookup_table() {
    // Create a lookup table that converts strings into the equivalent ShaderCaps member-pointers.
    static CapsLookupTable* sCapsLookupTable = new CapsLookupTable({
        CapsLookupTable::Pair("mustDoOpBetweenFloorAndAbs",
                              &ShaderCaps::fMustDoOpBetweenFloorAndAbs),
        CapsLookupTable::Pair("mustGuardDivisionEvenAfterExplicitZeroCheck",
                              &ShaderCaps::fMustGuardDivisionEvenAfterExplicitZeroCheck),
        CapsLookupTable::Pair("atan2ImplementedAsAtanYOverX",
                              &ShaderCaps::fAtan2ImplementedAsAtanYOverX),
        CapsLookupTable::Pair("floatIs32Bits",
                              &ShaderCaps::fFloatIs32Bits),
        CapsLookupTable::Pair("integerSupport",
                              &ShaderCaps::fIntegerSupport),
        CapsLookupTable::Pair("builtinDeterminantSupport",
                              &ShaderCaps::fBuiltinDeterminantSupport),
        CapsLookupTable::Pair("rewriteMatrixVectorMultiply",
                              &ShaderCaps::fRewriteMatrixVectorMultiply),
    });
    return *sCapsLookupTable;
}

}  // namespace

std::string_view Setting::name() const {
    for (const auto& [name, capsPtr] : caps_lookup_table()) {
        if (capsPtr == fCapsPtr) {
            return name;
        }
    }
    SkUNREACHABLE;
}

std::unique_ptr<Expression> Setting::Convert(const Context& context,
                                             Position pos,
                                             const std::string_view& name) {
    SkASSERT(context.fConfig);

    if (ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
        context.fErrors->error(pos, "name 'sk_Caps' is reserved");
        return nullptr;
    }

    const CapsPtr* capsPtr = caps_lookup_table().find(name);
    if (!capsPtr) {
        context.fErrors->error(pos, "unknown capability flag '" + std::string(name) + "'");
        return nullptr;
    }

    return Setting::Make(context, pos, *capsPtr);
}

std::unique_ptr<Expression> Setting::Make(const Context& context, Position pos, CapsPtr capsPtr) {
    if (context.fCaps) {
        // We know the caps values--return a boolean literal.
        return Literal::MakeBool(context, pos, context.fCaps->*capsPtr);
    }

    // We don't know the caps values yet--generate a Setting IRNode.
    return std::make_unique<Setting>(pos, capsPtr, context.fTypes.fBool.get());
}

std::unique_ptr<Expression> Setting::toLiteral(const Context& context) const {
    SkASSERT(context.fCaps);
    return Literal::MakeBool(fPosition, context.fCaps->*fCapsPtr, &this->type());
}


}  // namespace SkSL
