/*
 * 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 "Formatter.h"
#include "Interface.h"
#include "Method.h"
#include "Scope.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 {
        baseName = ifaceName.substr(1);  // cut off the leading 'I'.
    }

    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.version().substr(1) << "\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




