/*
 * Copyright (C) 2019 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 "AidlHelper.h"
#include "CompoundType.h"
#include "Coordinator.h"
#include "EnumType.h"
#include "Interface.h"
#include "NamedType.h"
#include "TypeDef.h"

namespace android {

static void emitConversionNotes(Formatter& out, const NamedType& namedType) {
    out << "// This is the HIDL definition of " << namedType.fqName().string() << "\n";
    out.pushLinePrefix("// ");
    namedType.emitHidlDefinition(out);
    out.popLinePrefix();
    out << "\n";
}

static void emitTypeDefAidlDefinition(Formatter& out, const TypeDef& typeDef) {
    out << "// Cannot convert typedef " << typeDef.referencedType()->definedName() << " "
        << typeDef.fqName().string() << " since AIDL does not support typedefs.\n";
    emitConversionNotes(out, typeDef);
}

static void emitEnumAidlDefinition(Formatter& out, const EnumType& enumType) {
    const ScalarType* scalar = enumType.storageType()->resolveToScalarType();
    CHECK(scalar != nullptr) << enumType.typeName();

    enumType.emitDocComment(out);
    out << "@VintfStability\n";
    out << "@Backing(type=\"" << AidlHelper::getAidlType(*scalar, enumType.fqName()) << "\")\n";
    out << "enum " << AidlHelper::getAidlType(enumType, enumType.fqName()) << " ";
    out.block([&] {
        enumType.forEachValueFromRoot([&](const EnumValue* value) {
            value->emitDocComment(out);
            out << value->name();
            if (!value->isAutoFill()) {
                out << " = " << value->constExpr()->expression();
            }
            out << ",\n";
        });
    });
}

static void emitCompoundTypeAidlDefinition(
        Formatter& out, const CompoundType& compoundType,
        const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
    // Get all of the subtypes and fields from this type and any older versions
    // that it references.
    const auto& it = processedTypes.find(&compoundType);
    CHECK(it != processedTypes.end()) << "Failed to find " << compoundType.fullName();
    const ProcessedCompoundType& processedType = it->second;

    compoundType.emitDocComment(out);
    out << "@VintfStability\n";
    if (compoundType.style() == CompoundType::STYLE_STRUCT) {
        out << "parcelable " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
    } else {
        if (compoundType.style() == CompoundType::STYLE_UNION) {
            out << "// FIXME Any discriminators should be removed since they are automatically "
                   "added.\n";
        }
        out << "union " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
    }
    out.block([&] {
        // Emit all of the fields from the processed type
        for (auto const& fieldWithVersion : processedType.fields) {
            fieldWithVersion.field->emitDocComment(out);
            std::string aidlType =
                    AidlHelper::getAidlType(*fieldWithVersion.field->get(), compoundType.fqName());
            out << aidlType << " " << fieldWithVersion.field->name() << ";\n";
        }
    });
    out << "\n\n";
}

// TODO: Enum/Typedef should just emit to hidl-error.log or similar
void AidlHelper::emitAidl(
        const NamedType& namedType, const Coordinator& coordinator,
        const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
    Formatter out = getFileWithHeader(namedType, coordinator, processedTypes);
    if (namedType.isTypeDef()) {
        const TypeDef& typeDef = static_cast<const TypeDef&>(namedType);
        emitTypeDefAidlDefinition(out, typeDef);
    } else if (namedType.isCompoundType()) {
        const CompoundType& compoundType = static_cast<const CompoundType&>(namedType);
        emitCompoundTypeAidlDefinition(out, compoundType, processedTypes);
    } else if (namedType.isEnum()) {
        const EnumType& enumType = static_cast<const EnumType&>(namedType);
        emitEnumAidlDefinition(out, enumType);
    } else if (namedType.isInterface()) {
        const Interface& iface = static_cast<const Interface&>(namedType);
        emitAidl(iface, coordinator, processedTypes);
    } else {
        out << "// TODO: Fix this " << namedType.definedName() << "\n";
    }
}

}  // namespace android
