/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "EnumType.h"

#include <hidl-util/Formatter.h>
#include <inttypes.h>
#include <iostream>
#include <unordered_map>

#include "Annotation.h"
#include "Location.h"
#include "ScalarType.h"

namespace android {

EnumType::EnumType(const char* localName, const FQName& fullName, const Location& location,
                   const Reference<Type>& storageType, Scope* parent)
    : Scope(localName, fullName, location, parent), mValues(), mStorageType(storageType) {}

const Type *EnumType::storageType() const {
    return mStorageType.get();
}

const std::vector<EnumValue *> &EnumType::values() const {
    return mValues;
}

void EnumType::forEachValueFromRoot(const std::function<void(EnumValue*)> f) const {
    std::vector<const EnumType*> chain = typeChain();
    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto& type = *it;
        for (EnumValue* v : type->values()) {
            f(v);
        }
    }
}

void EnumType::addValue(EnumValue* value) {
    CHECK(value != nullptr);
    mValues.push_back(value);
}

status_t EnumType::resolveInheritance() {
    const EnumType* prevType = nullptr;
    EnumValue* prevValue = nullptr;

    for (const auto* type : superTypeChain()) {
        if (!type->values().empty()) {
            prevType = type;
            prevValue = type->values().back();
            break;
        }
    }

    for (auto* value : mValues) {
        value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
        prevType = this;
        prevValue = value;
    }

    return Scope::resolveInheritance();
}

std::vector<const Reference<Type>*> EnumType::getReferences() const {
    return {&mStorageType};
}

std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
    std::vector<const ConstantExpression*> ret;
    for (const auto* value : mValues) {
        ret.push_back(value->constExpr());
    }
    return ret;
}

status_t EnumType::validate() const {
    CHECK(getSubTypes().empty());

    if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
        std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
                  << ") specified at " << mStorageType.location() << "\n";
        return UNKNOWN_ERROR;
    }

    status_t err = validateUniqueNames();
    if (err != OK) return err;

    return Scope::validate();
}

status_t EnumType::validateUniqueNames() const {
    std::unordered_map<std::string, const EnumType*> registeredValueNames;
    for (const auto* type : superTypeChain()) {
        for (const auto* enumValue : type->mValues) {
            // No need to check super value uniqueness
            registeredValueNames[enumValue->name()] = type;
        }
    }

    for (const auto* value : mValues) {
        auto registered = registeredValueNames.find(value->name());

        if (registered != registeredValueNames.end()) {
            const EnumType* definedInType = registered->second;

            if (definedInType == this) {
                // Defined in this enum
                std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
            } else {
                // Defined in super enum
                std::cerr << "ERROR: Redefinition of value '" << value->name()
                          << "' defined in enum '" << definedInType->fullName() << "'";
            }
            std::cerr << " at " << value->location() << "\n";
            return UNKNOWN_ERROR;
        }

        registeredValueNames[value->name()] = this;
    }

    return OK;
}

bool EnumType::isElidableType() const {
    return mStorageType->isElidableType();
}

const ScalarType *EnumType::resolveToScalarType() const {
    return mStorageType->resolveToScalarType();
}

std::string EnumType::typeName() const {
    return "enum " + localName();
}

bool EnumType::isEnum() const {
    return true;
}

bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
    return true;
}

std::string EnumType::getCppType(StorageMode,
                                 bool /* specifyNamespaces */) const {
    return fullName();
}

std::string EnumType::getJavaType(bool forInitializer) const {
    return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
}

std::string EnumType::getJavaSuffix() const {
    return mStorageType->resolveToScalarType()->getJavaSuffix();
}

std::string EnumType::getJavaWrapperType() const {
    return mStorageType->resolveToScalarType()->getJavaWrapperType();
}

std::string EnumType::getVtsType() const {
    return "TYPE_ENUM";
}

std::string EnumType::getBitfieldCppType(StorageMode /* mode */, bool specifyNamespaces) const {
    const std::string space = specifyNamespaces ? "::android::hardware::" : "";
    return space + "hidl_bitfield<" + (specifyNamespaces ? fullName() : localName()) + ">";
}

std::string EnumType::getBitfieldJavaType(bool forInitializer) const {
    return resolveToScalarType()->getJavaType(forInitializer);
}

std::string EnumType::getBitfieldJavaWrapperType() const {
    return resolveToScalarType()->getJavaWrapperType();
}

LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
    std::vector<const EnumType*> chain = typeChain();
    for (auto it = chain.begin(); it != chain.end(); ++it) {
        const auto &type = *it;
        for(EnumValue *v : type->values()) {
            if(v->name() == name) {
                return v;
            }
        }
    }
    return nullptr;
}

void EnumType::emitReaderWriter(
        Formatter &out,
        const std::string &name,
        const std::string &parcelObj,
        bool parcelObjIsPointer,
        bool isReader,
        ErrorMode mode) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    scalarType->emitReaderWriterWithCast(
            out,
            name,
            parcelObj,
            parcelObjIsPointer,
            isReader,
            mode,
            true /* needsCast */);
}

void EnumType::emitJavaFieldReaderWriter(
        Formatter &out,
        size_t depth,
        const std::string &parcelName,
        const std::string &blobName,
        const std::string &fieldName,
        const std::string &offset,
        bool isReader) const {
    return mStorageType->emitJavaFieldReaderWriter(
            out, depth, parcelName, blobName, fieldName, offset, isReader);
}

void EnumType::emitTypeDeclarations(Formatter& out) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    const std::string storageType = scalarType->getCppStackType();

    out << "enum class "
        << localName()
        << " : "
        << storageType
        << " {\n";

    out.indent();

    std::vector<const EnumType*> chain = typeChain();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            out << entry->name();

            std::string value = entry->cppValue(scalarType->getKind());
            CHECK(!value.empty()); // use autofilled values for c++.
            out << " = " << value;

            out << ",";

            std::string comment = entry->comment();
            if (!comment.empty()) {
                out << " // " << comment;
            }

            out << "\n";
        }
    }

    out.unindent();
    out << "};\n\n";
}

void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
    const ScalarType* scalarType = mStorageType->resolveToScalarType();
    const std::string storageType = scalarType->getCppStackType();

    out << "enum class " << localName() << " : " << storageType << ";\n";
}

void EnumType::emitIteratorDeclaration(Formatter& out) const {
    size_t elementCount = 0;
    for (const auto* type : typeChain()) {
        elementCount += type->mValues.size();
    }

    out << "template<> struct hidl_enum_iterator<" << getCppStackType() << ">\n";
    out.block([&] {
        out << "const " << getCppStackType() << "* begin() { return static_begin(); }\n";
        out << "const " << getCppStackType() << "* end() { return begin() + " << elementCount
            << "; }\n";
        out << "private:\n";
        out << "static const " << getCppStackType() << "* static_begin() ";
        out.block([&] {
            out << "static const " << getCppStackType() << " kVals[" << elementCount << "] ";
            out.block([&] {
                auto enumerators = typeChain();
                std::reverse(enumerators.begin(), enumerators.end());
                for (const auto* type : enumerators) {
                    for (const auto* enumValue : type->mValues) {
                        out << fullName() << "::" << enumValue->name() << ",\n";
                    }
                }
            }) << ";\n";
            out << "return &kVals[0];\n";
        });
    }) << ";\n\n";
}

void EnumType::emitEnumBitwiseOperator(
        Formatter &out,
        bool lhsIsEnum,
        bool rhsIsEnum,
        const std::string &op) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    const std::string storageType = scalarType->getCppStackType();

    out << "constexpr "
        << storageType
        << " operator"
        << op
        << "(const "
        << (lhsIsEnum ? fullName() : storageType)
        << " lhs, const "
        << (rhsIsEnum ? fullName() : storageType)
        << " rhs) {\n";

    out.indent([&] {
        out << "return static_cast<"
            << storageType
            << ">(";

        if (lhsIsEnum) {
            out << "static_cast<"
                << storageType
                << ">(lhs)";
        } else {
            out << "lhs";
        }
        out << " " << op << " ";
        if (rhsIsEnum) {
            out << "static_cast<"
                << storageType
                << ">(rhs)";
        } else {
            out << "rhs";
        }
        out << ");\n";
    });

    out << "}\n\n";
}

void EnumType::emitBitFieldBitwiseAssignmentOperator(
        Formatter &out,
        const std::string &op) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    const std::string storageType = scalarType->getCppStackType();

    out << "constexpr " << storageType << " &operator" << op << "=("
        << storageType << "& v, const " << fullName() << " e) {\n";

    out.indent([&] {
        out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
        out << "return v;\n";
    });

    out << "}\n\n";
}

void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
    out << "namespace android {\n";
    out << "namespace hardware {\n";

    emitIteratorDeclaration(out);

    out << "}  // namespace hardware\n";
    out << "}  // namespace android\n";
}

void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");

    emitBitFieldBitwiseAssignmentOperator(out, "|");
    emitBitFieldBitwiseAssignmentOperator(out, "&");

    // TODO(b/65200821): remove these ifndefs
    out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
        // toString for bitfields, equivalent to dumpBitfield in Java
        out << "template<typename>\n"
            << "std::string toString("
            << resolveToScalarType()->getCppArgumentType()
            << " o);\n";
        out << "template<>\n"
            << "std::string toString<" << getCppStackType() << ">("
            << resolveToScalarType()->getCppArgumentType()
            << " o);\n\n";

        // toString for enum itself
        out << "std::string toString("
            << getCppArgumentType()
            << " o);\n\n";
    out << "#else\n";
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    out << "template<typename>\n"
        << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
        << " o);\n";
    out << "template<>\n"
        << "inline std::string toString<" << getCppStackType() << ">("
        << scalarType->getCppArgumentType() << " o) ";
    out.block([&] {
        // include toHexString for scalar types
        out << "using ::android::hardware::details::toHexString;\n"
            << "std::string os;\n"
            << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
            << "bool first = true;\n";
        forEachValueFromRoot([&](EnumValue* value) {
            std::string valueName = fullName() + "::" + value->name();
            out.sIf("(o & " + valueName + ")" +
                    " == static_cast<" + scalarType->getCppStackType() +
                    ">(" + valueName + ")", [&] {
                out << "os += (first ? \"\" : \" | \");\n"
                    << "os += \"" << value->name() << "\";\n"
                    << "first = false;\n"
                    << "flipped |= " << valueName << ";\n";
            }).endl();
        });
        // put remaining bits
        out.sIf("o != flipped", [&] {
            out << "os += (first ? \"\" : \" | \");\n";
            scalarType->emitHexDump(out, "os", "o & (~flipped)");
        });
        out << "os += \" (\";\n";
        scalarType->emitHexDump(out, "os", "o");
        out << "os += \")\";\n";

        out << "return os;\n";
    }).endl().endl();

    out << "static inline std::string toString(" << getCppArgumentType() << " o) ";

    out.block([&] {
        out << "using ::android::hardware::details::toHexString;\n";
        forEachValueFromRoot([&](EnumValue* value) {
            out.sIf("o == " + fullName() + "::" + value->name(), [&] {
                out << "return \"" << value->name() << "\";\n";
            }).endl();
        });
        out << "std::string os;\n";
        scalarType->emitHexDump(out, "os",
            "static_cast<" + scalarType->getCppStackType() + ">(o)");
        out << "return os;\n";
    }).endl().endl();
    out << "#endif  // REALLY_IS_HIDL_INTERNAL_LIB\n";
}

void EnumType::emitTypeDefinitions(Formatter& out, const std::string& /* prefix */) const {
    // TODO(b/65200821): remove toString from .cpp once all prebuilts are rebuilt

    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    out << "template<>\n"
        << "std::string toString<" << getCppStackType() << ">("
        << scalarType->getCppArgumentType()
        << " o) ";
    out.block([&] {
        // include toHexString for scalar types
        out << "using ::android::hardware::details::toHexString;\n"
            << "std::string os;\n"
            << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
            << "bool first = true;\n";

        forEachValueFromRoot([&](EnumValue* value) {
            std::string valueName = fullName() + "::" + value->name();
            out.sIf("(o & " + valueName + ")" +
                    " == static_cast<" + scalarType->getCppStackType() +
                    ">(" + valueName + ")", [&] {
                out << "os += (first ? \"\" : \" | \");\n"
                    << "os += \"" << value->name() << "\";\n"
                    << "first = false;\n"
                    << "flipped |= " << valueName << ";\n";
            }).endl();
        });
        // put remaining bits
        out.sIf("o != flipped", [&] {
            out << "os += (first ? \"\" : \" | \");\n";
            scalarType->emitHexDump(out, "os", "o & (~flipped)");
        });
        out << "os += \" (\";\n";
        scalarType->emitHexDump(out, "os", "o");
        out << "os += \")\";\n";

        out << "return os;\n";
    }).endl().endl();

    out << "std::string toString("
        << getCppArgumentType()
        << " o) ";

    out.block([&] {
        out << "using ::android::hardware::details::toHexString;\n";

        forEachValueFromRoot([&](EnumValue* value) {
            out.sIf("o == " + fullName() + "::" + value->name(), [&] {
                out << "return \"" << value->name() << "\";\n";
            }).endl();
        });

        out << "std::string os;\n";
        scalarType->emitHexDump(out, "os",
            "static_cast<" + scalarType->getCppStackType() + ">(o)");
        out << "return os;\n";
    }).endl().endl();
}

void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    out << "public "
        << (atTopLevel ? "" : "static ")
        << "final class "
        << localName()
        << " {\n";

    out.indent();

    const std::string typeName =
        scalarType->getJavaType(false /* forInitializer */);

    std::vector<const EnumType*> chain = typeChain();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            out << "public static final "
                << typeName
                << " "
                << entry->name()
                << " = ";

            // javaValue will make the number signed.
            std::string value = entry->javaValue(scalarType->getKind());
            CHECK(!value.empty()); // use autofilled values for java.
            out << value;

            out << ";";

            std::string comment = entry->comment();
            if (!comment.empty()) {
                out << " // " << comment;
            }

            out << "\n";
        }
    }

    out << "public static final String toString("
        << typeName << " o) ";
    out.block([&] {
        forEachValueFromRoot([&](EnumValue* value) {
            out.sIf("o == " + value->name(), [&] {
                out << "return \"" << value->name() << "\";\n";
            }).endl();
        });
        out << "return \"0x\" + ";
        scalarType->emitConvertToJavaHexString(out, "o");
        out << ";\n";
    }).endl();

    auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
    auto bitfieldWrapperType = getBitfieldJavaWrapperType();
    out << "\n"
        << "public static final String dumpBitfield("
        << bitfieldType << " o) ";
    out.block([&] {
        out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
        out << bitfieldType << " flipped = 0;\n";
        forEachValueFromRoot([&](EnumValue* value) {
            if (value->constExpr()->castSizeT() == 0) {
                out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
                return;  // continue to next value
            }
            out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
                out << "list.add(\"" << value->name() << "\");\n";
                out << "flipped |= " << value->name() << ";\n";
            }).endl();
        });
        // put remaining bits
        out.sIf("o != flipped", [&] {
            out << "list.add(\"0x\" + ";
            scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
            out << ");\n";
        }).endl();
        out << "return String.join(\" | \", list);\n";
    }).endl().endl();

    out.unindent();
    out << "};\n\n";
}

void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();

    out << "name: \"" << fullName() << "\"\n";
    out << "type: " << getVtsType() << "\n";
    out << "enum_value: {\n";
    out.indent();

    out << "scalar_type: \""
        << scalarType->getVtsScalarType()
        << "\"\n\n";
    std::vector<const EnumType*> chain = typeChain();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            out << "enumerator: \"" << entry->name() << "\"\n";
            out << "scalar_value: {\n";
            out.indent();
            // use autofilled values for vts.
            std::string value = entry->value(scalarType->getKind());
            CHECK(!value.empty());
            out << mStorageType->resolveToScalarType()->getVtsScalarType()
                << ": "
                << value
                << "\n";
            out.unindent();
            out << "}\n";
        }
    }

    out.unindent();
    out << "}\n";
}

void EnumType::emitVtsAttributeType(Formatter& out) const {
    out << "type: " << getVtsType() << "\n";
    out << "predefined_type: \"" << fullName() << "\"\n";
}

void EnumType::emitJavaDump(
        Formatter &out,
        const std::string &streamName,
        const std::string &name) const {
    out << streamName << ".append(" << fqName().javaName() << ".toString("
        << name << "));\n";
}

std::vector<const EnumType*> EnumType::typeChain() const {
    std::vector<const EnumType*> types;
    for (const EnumType* type = this; type != nullptr;) {
        types.push_back(type);

        const Type* superType = type->storageType();
        if (superType != nullptr && superType->isEnum()) {
            type = static_cast<const EnumType*>(superType);
        } else {
            type = nullptr;
        }
    }

    return types;
}

std::vector<const EnumType*> EnumType::superTypeChain() const {
    const Type* superType = storageType();
    if (superType == nullptr || !superType->isEnum()) {
        return {};
    }
    return static_cast<const EnumType*>(superType)->typeChain();
}

void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
    mStorageType->getAlignmentAndSize(align, size);
}

const Annotation *EnumType::findExportAnnotation() const {
    for (const auto &annotation : annotations()) {
        if (annotation->name() == "export") {
            return annotation;
        }
    }

    return nullptr;
}

void EnumType::appendToExportedTypesVector(
        std::vector<const Type *> *exportedTypes) const {
    if (findExportAnnotation() != nullptr) {
        exportedTypes->push_back(this);
    }
}

void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
    const Annotation *annotation = findExportAnnotation();
    CHECK(annotation != nullptr);

    std::string name = localName();

    const AnnotationParam *nameParam = annotation->getParam("name");
    if (nameParam != nullptr) {
        name = nameParam->getSingleString();
    }

    bool exportParent = true;
    const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
    if (exportParentParam != nullptr) {
        exportParent = exportParentParam->getSingleBool();
    }

    std::string valuePrefix;
    const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
    if (prefixParam != nullptr) {
        valuePrefix = prefixParam->getSingleString();
    }

    std::string valueSuffix;
    const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
    if (suffixParam != nullptr) {
        valueSuffix = suffixParam->getSingleString();
    }

    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    std::vector<const EnumType *> chain;
    if (exportParent) {
        chain = typeChain();
    } else {
        chain = { this };
    }

    if (forJava) {
        if (!name.empty()) {
            out << "public final class "
                << name
                << " {\n";

            out.indent();
        } else {
            out << "// Values declared in " << localName() << " follow.\n";
        }

        const std::string typeName =
            scalarType->getJavaType(false /* forInitializer */);

        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
            const auto &type = *it;

            for (const auto &entry : type->values()) {
                out << "public static final "
                    << typeName
                    << " "
                    << valuePrefix
                    << entry->name()
                    << valueSuffix
                    << " = ";

                // javaValue will make the number signed.
                std::string value = entry->javaValue(scalarType->getKind());
                CHECK(!value.empty()); // use autofilled values for java.
                out << value;

                out << ";";

                std::string comment = entry->comment();
                if (!comment.empty()) {
                    out << " // " << comment;
                }

                out << "\n";
            }
        }

        if (!name.empty()) {
            out.unindent();
            out << "};\n";
        }
        out << "\n";

        return;
    }

    if (!name.empty()) {
        out << "typedef ";
    }

    out << "enum {\n";

    out.indent();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            out << valuePrefix << entry->name() << valueSuffix;

            std::string value = entry->cppValue(scalarType->getKind());
            CHECK(!value.empty()); // use autofilled values for c++.
            out << " = " << value;

            out << ",";

            std::string comment = entry->comment();
            if (!comment.empty()) {
                out << " // " << comment;
            }

            out << "\n";
        }
    }

    out.unindent();
    out << "}";

    if (!name.empty()) {
        out << " " << name;
    }

    out << ";\n\n";
}

////////////////////////////////////////////////////////////////////////////////

EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location)
    : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}

std::string EnumValue::name() const {
    return mName;
}

std::string EnumValue::value(ScalarType::Kind castKind) const {
    CHECK(mValue != nullptr);
    return mValue->value(castKind);
}

std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
    CHECK(mValue != nullptr);
    return mValue->cppValue(castKind);
}
std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
    CHECK(mValue != nullptr);
    return mValue->javaValue(castKind);
}

std::string EnumValue::comment() const {
    CHECK(mValue != nullptr);
    if (mValue->descriptionIsTrivial()) return "";
    return mValue->description();
}

ConstantExpression *EnumValue::constExpr() const {
    CHECK(mValue != nullptr);
    return mValue;
}

void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
    // Value is defined explicitly
    if (mValue != nullptr) return;

    CHECK((prevType == nullptr) == (prevValue == nullptr));

    mIsAutoFill = true;
    if (prevValue == nullptr) {
        mValue = ConstantExpression::Zero(type->getKind()).release();
    } else {
        std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
        auto* prevReference = new ReferenceConstantExpression(
            Reference<LocalIdentifier>(prevValue, mLocation), description);
        mValue = prevReference->addOne(type->getKind()).release();
    }
}

bool EnumValue::isAutoFill() const {
    return mIsAutoFill;
}

bool EnumValue::isEnumValue() const {
    return true;
}

const Location& EnumValue::location() const {
    return mLocation;
}

////////////////////////////////////////////////////////////////////////////////

BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent) {}

bool BitFieldType::isBitField() const {
    return true;
}

const EnumType* BitFieldType::getElementEnumType() const {
    CHECK(mElementType.get() != nullptr && mElementType->isEnum());
    return static_cast<const EnumType*>(mElementType.get());
}

std::string BitFieldType::templatedTypeName() const {
    return "mask";
}

bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
    return elementType->isEnum();
}

const ScalarType *BitFieldType::resolveToScalarType() const {
    return mElementType->resolveToScalarType();
}

std::string BitFieldType::getCppType(StorageMode mode,
                                 bool specifyNamespaces) const {
    return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
}

std::string BitFieldType::getJavaType(bool forInitializer) const {
    return getElementEnumType()->getBitfieldJavaType(forInitializer);
}

std::string BitFieldType::getJavaSuffix() const {
    return resolveToScalarType()->getJavaSuffix();
}

std::string BitFieldType::getJavaWrapperType() const {
    return getElementEnumType()->getBitfieldJavaWrapperType();
}

std::string BitFieldType::getVtsType() const {
    return "TYPE_MASK";
}

bool BitFieldType::isElidableType() const {
    return resolveToScalarType()->isElidableType();
}

bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
    return resolveToScalarType()->canCheckEquality(visited);
}

void BitFieldType::emitVtsAttributeType(Formatter& out) const {
    out << "type: " << getVtsType() << "\n";
    out << "scalar_type: \""
        << mElementType->resolveToScalarType()->getVtsScalarType()
        << "\"\n";
    out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
        << "\"\n";
}

void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
    resolveToScalarType()->getAlignmentAndSize(align, size);
}

void BitFieldType::emitReaderWriter(
        Formatter &out,
        const std::string &name,
        const std::string &parcelObj,
        bool parcelObjIsPointer,
        bool isReader,
        ErrorMode mode) const {
    resolveToScalarType()->emitReaderWriterWithCast(
            out,
            name,
            parcelObj,
            parcelObjIsPointer,
            isReader,
            mode,
            true /* needsCast */);
}

const EnumType* BitFieldType::getEnumType() const {
    CHECK(mElementType->isEnum());
    return static_cast<const EnumType*>(mElementType.get());
}

// a bitfield maps to the underlying scalar type in C++, so operator<< is
// already defined. We can still emit useful information if the bitfield is
// in a struct / union by overriding emitDump as below.
void BitFieldType::emitDump(
        Formatter &out,
        const std::string &streamName,
        const std::string &name) const {
    out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
        << "::toString<" << getEnumType()->getCppStackType()
        << ">(" << name << ");\n";
}

void BitFieldType::emitJavaDump(
        Formatter &out,
        const std::string &streamName,
        const std::string &name) const {
    out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
        << name << "));\n";
}

void BitFieldType::emitJavaFieldReaderWriter(
        Formatter &out,
        size_t depth,
        const std::string &parcelName,
        const std::string &blobName,
        const std::string &fieldName,
        const std::string &offset,
        bool isReader) const {
    return resolveToScalarType()->emitJavaFieldReaderWriter(
            out, depth, parcelName, blobName, fieldName, offset, isReader);
}

}  // namespace android

