/*
 * 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 "AST.h"

#include "Annotation.h"
#include "Coordinator.h"
#include "Interface.h"
#include "Method.h"
#include "Scope.h"

#include <hidl-util/Formatter.h>
#include <android-base/logging.h>
#include <string>
#include <vector>

namespace android {

status_t AST::emitVtsTypeDeclarations(Formatter &out) const {
    std::set<AST *> allImportedASTs;
    return emitVtsTypeDeclarationsHelper(out, &allImportedASTs);
}

status_t AST::emitVtsTypeDeclarationsHelper(
        Formatter &out,
        std::set<AST *> *allImportSet) const {
    // First, generate vts type declaration for all imported AST.
    for (const auto &ast : mImportedASTs) {
        // Already processed, skip.
        if (allImportSet->find(ast) != allImportSet->end()) {
            continue;
        }
        allImportSet->insert(ast);
        std::string ifaceName;
        // We only care about types.hal.
        if (!ast->isInterface(&ifaceName)) {
            status_t status = ast->emitVtsTypeDeclarationsHelper(
                    out, allImportSet);
            if (status != OK) {
                return status;
            }
        }
    }
    // Next, generate vts type declaration for the current AST.
    for (const auto &type : mRootScope->getSubTypes()) {
        // Skip for TypeDef as it is just an alias of a defined type.
        if (type->isTypeDef()) {
            continue;
        }
        out << "attribute: {\n";
        out.indent();
        status_t status = type->emitVtsTypeDeclarations(out);
        if (status != OK) {
            return status;
        }
        out.unindent();
        out << "}\n\n";
    }
    return OK;
}

status_t AST::generateVts(const std::string &outputPath) const {
    std::string path = outputPath;
    path.append(mCoordinator->convertPackageRootToPath(mPackage));
    path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));

    std::string ifaceName;
    std::string baseName;

    bool isInterface = true;
    if (!AST::isInterface(&ifaceName)) {
        baseName = "types";
        isInterface = false;
    } else {
        const Interface *iface = mRootScope->getInterface();
        baseName = iface->getBaseName();
    }

    path.append(baseName);
    path.append(".vts");

    CHECK(Coordinator::MakeParentHierarchy(path));
    FILE *file = fopen(path.c_str(), "w");

    if (file == NULL) {
        return -errno;
    }

    Formatter out(file);

    out << "component_class: HAL_HIDL\n";
    out << "component_type_version: " << mPackage.getPackageFullVersion()
        << "\n";
    out << "component_name: \""
        << (isInterface ? ifaceName : "types")
        << "\"\n\n";

    out << "package: \"" << mPackage.package() << "\"\n\n";

    for (const auto &item : mImportedNames) {
        out << "import: \"" << item.string() << "\"\n";
    }

    out << "\n";

    if (isInterface) {
        const Interface *iface = mRootScope->getInterface();
        out << "interface: {\n";
        out.indent();

        std::vector<const Interface *> chain;
        while (iface != NULL) {
            chain.push_back(iface);
            iface = iface->superType();
        }

        // Generate all the attribute declarations first.
        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
            const Interface *superInterface = *it;
            status_t status = superInterface->emitVtsAttributeDeclaration(out);
            if (status != OK) {
                return status;
            }
        }

        // Generate all the method declarations.
        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
            const Interface *superInterface = *it;
            status_t status = superInterface->emitVtsMethodDeclaration(out);
            if (status != OK) {
                return status;
            }
        }

        out.unindent();
        out << "}\n";
    } else {
        status_t status = emitVtsTypeDeclarations(out);
        if (status != OK) {
            return status;
        }
    }
    return OK;
}

}  // namespace android




