/*
 * 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 "Coordinator.h"
#include "EnumType.h"
#include "FmqType.h"
#include "HandleType.h"
#include "Interface.h"
#include "Location.h"
#include "Scope.h"
#include "TypeDef.h"

#include <android-base/logging.h>
#include <hidl-util/FQName.h>
#include <hidl-util/Formatter.h>
#include <hidl-util/StringHelper.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>

namespace android {

AST::AST(const Coordinator* coordinator, const Hash* fileHash)
    : mCoordinator(coordinator),
      mFileHash(fileHash),
      mRootScope("(root scope)", FQName(), Location::startOf(fileHash->getPath()),
                 nullptr /* parent */) {}

Scope* AST::getRootScope() {
    return &mRootScope;
}

// used by the parser.
void AST::addSyntaxError() {
    mSyntaxErrors++;
}

size_t AST::syntaxErrors() const {
    return mSyntaxErrors;
}

const std::string& AST::getFilename() const {
    return mFileHash->getPath();
}
const Hash* AST::getFileHash() const {
    return mFileHash;
}

bool AST::setPackage(const char *package) {
    if (!mPackage.setTo(package)) {
        return false;
    }

    if (mPackage.package().empty()
            || mPackage.version().empty()
            || !mPackage.name().empty()) {
        return false;
    }

    return true;
}

FQName AST::package() const {
    return mPackage;
}

bool AST::isInterface() const {
    return mRootScope.getInterface() != nullptr;
}

bool AST::containsInterfaces() const {
    return mRootScope.containsInterfaces();
}

status_t AST::postParse() {
    status_t err;

    // lookupTypes is the first pass.
    err = lookupTypes();
    if (err != OK) return err;
    // validateDefinedTypesUniqueNames is the first call
    // after lookup, as other errors could appear because
    // user meant different type than we assumed.
    err = validateDefinedTypesUniqueNames();
    if (err != OK) return err;
    // topologicalReorder is before resolveInheritance, as we
    // need to have no cycle while getting parent class.
    err = topologicalReorder();
    if (err != OK) return err;
    err = resolveInheritance();
    if (err != OK) return err;
    err = lookupLocalIdentifiers();
    if (err != OK) return err;
    // checkAcyclicConstantExpressions is after resolveInheritance,
    // as resolveInheritance autofills enum values.
    err = checkAcyclicConstantExpressions();
    if (err != OK) return err;
    err = evaluate();
    if (err != OK) return err;
    err = validate();
    if (err != OK) return err;
    err = checkForwardReferenceRestrictions();
    if (err != OK) return err;
    err = gatherReferencedTypes();
    if (err != OK) return err;

    // Make future packages not to call passes
    // for processed types and expressions
    constantExpressionRecursivePass(
        [](ConstantExpression* ce) {
            ce->setPostParseCompleted();
            return OK;
        },
        true /* processBeforeDependencies */);
    std::unordered_set<const Type*> visited;
    mRootScope.recursivePass(
        [](Type* type) {
            type->setPostParseCompleted();
            return OK;
        },
        &visited);

    return OK;
}

status_t AST::constantExpressionRecursivePass(
    const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) {
    std::unordered_set<const Type*> visitedTypes;
    std::unordered_set<const ConstantExpression*> visitedCE;
    return mRootScope.recursivePass(
        [&](Type* type) -> status_t {
            for (auto* ce : type->getConstantExpressions()) {
                status_t err = ce->recursivePass(func, &visitedCE, processBeforeDependencies);
                if (err != OK) return err;
            }
            return OK;
        },
        &visitedTypes);
}

status_t AST::lookupTypes() {
    std::unordered_set<const Type*> visited;
    return mRootScope.recursivePass(
        [&](Type* type) -> status_t {
            Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();

            for (auto* nextRef : type->getReferences()) {
                if (nextRef->isResolved()) {
                    continue;
                }

                Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
                if (nextType == nullptr) {
                    std::cerr << "ERROR: Failed to lookup type '"
                              << nextRef->getLookupFqName().string() << "' at "
                              << nextRef->location() << "\n";
                    return UNKNOWN_ERROR;
                }
                nextRef->set(nextType);
            }

            return OK;
        },
        &visited);
}

status_t AST::gatherReferencedTypes() {
    std::unordered_set<const Type*> visited;
    return mRootScope.recursivePass(
        [&](Type* type) -> status_t {
            for (auto* nextRef : type->getReferences()) {
                const Type *targetType = nextRef->get();
                if (targetType->isNamedType()) {
                    mReferencedTypeNames.insert(
                            static_cast<const NamedType *>(targetType)->fqName());
                }
            }

            return OK;
        },
        &visited);
}

status_t AST::lookupLocalIdentifiers() {
    std::unordered_set<const Type*> visitedTypes;
    std::unordered_set<const ConstantExpression*> visitedCE;

    return mRootScope.recursivePass(
        [&](Type* type) -> status_t {
            Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();

            for (auto* ce : type->getConstantExpressions()) {
                status_t err = ce->recursivePass(
                    [&](ConstantExpression* ce) {
                        for (auto* nextRef : ce->getReferences()) {
                            if (nextRef->isResolved()) continue;

                            LocalIdentifier* iden = lookupLocalIdentifier(*nextRef, scope);
                            if (iden == nullptr) return UNKNOWN_ERROR;
                            nextRef->set(iden);
                        }
                        return OK;
                    },
                    &visitedCE, true /* processBeforeDependencies */);
                if (err != OK) return err;
            }

            return OK;
        },
        &visitedTypes);
}

status_t AST::validateDefinedTypesUniqueNames() const {
    std::unordered_set<const Type*> visited;
    return mRootScope.recursivePass(
        [&](const Type* type) -> status_t {
            // We only want to validate type definition names in this place.
            if (type->isScope()) {
                return static_cast<const Scope*>(type)->validateUniqueNames();
            }
            return OK;
        },
        &visited);
}

status_t AST::resolveInheritance() {
    std::unordered_set<const Type*> visited;
    return mRootScope.recursivePass(&Type::resolveInheritance, &visited);
}

status_t AST::evaluate() {
    return constantExpressionRecursivePass(
        [](ConstantExpression* ce) {
            ce->evaluate();
            return OK;
        },
        false /* processBeforeDependencies */);
}

status_t AST::validate() const {
    std::unordered_set<const Type*> visited;
    return mRootScope.recursivePass(&Type::validate, &visited);
}

status_t AST::topologicalReorder() {
    std::unordered_map<const Type*, size_t> reversedOrder;
    std::unordered_set<const Type*> stack;
    status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status;
    if (err != OK) return err;

    std::unordered_set<const Type*> visited;
    mRootScope.recursivePass(
        [&](Type* type) {
            if (type->isScope()) {
                static_cast<Scope*>(type)->topologicalReorder(reversedOrder);
            }
            return OK;
        },
        &visited);
    return OK;
}

status_t AST::checkAcyclicConstantExpressions() const {
    std::unordered_set<const Type*> visitedTypes;
    std::unordered_set<const ConstantExpression*> visitedCE;
    std::unordered_set<const ConstantExpression*> stack;
    return mRootScope.recursivePass(
        [&](const Type* type) -> status_t {
            for (auto* ce : type->getConstantExpressions()) {
                status_t err = ce->checkAcyclic(&visitedCE, &stack).status;
                CHECK(err != OK || stack.empty());
                if (err != OK) return err;
            }
            return OK;
        },
        &visitedTypes);
}

status_t AST::checkForwardReferenceRestrictions() const {
    std::unordered_set<const Type*> visited;
    return mRootScope.recursivePass(
        [](const Type* type) -> status_t {
            for (const Reference<Type>* ref : type->getReferences()) {
                status_t err = type->checkForwardReferenceRestrictions(*ref);
                if (err != OK) return err;
            }
            return OK;
        },
        &visited);
}

bool AST::addImport(const char *import) {
    FQName fqName;
    if (!FQName::parse(import, &fqName)) {
        std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl;
        return false;
    }

    fqName.applyDefaults(mPackage.package(), mPackage.version());

    if (fqName.name().empty()) {
        // import a package

        std::vector<FQName> packageInterfaces;

        status_t err =
            mCoordinator->appendPackageInterfacesToVector(fqName,
                                                          &packageInterfaces);

        if (err != OK) {
            return false;
        }

        for (const auto &subFQName : packageInterfaces) {
            addToImportedNamesGranular(subFQName);

            // Do not enforce restrictions on imports.
            AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
            if (ast == nullptr) {
                return false;
            }
            // all previous single type imports are ignored.
            mImportedTypes.erase(ast);
        }

        return true;
    }

    addToImportedNamesGranular(fqName);

    // cases like android.hardware.foo@1.0::IFoo.Internal
    //            android.hardware.foo@1.0::Abc.Internal

    // assume it is an interface, and try to import it.
    const FQName interfaceName = fqName.getTopLevelType();
    // Do not enforce restrictions on imports.
    AST* importAST;
    status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
                                               Coordinator::Enforce::NONE);
    if (err != OK) return false;
    // importAST nullptr == file doesn't exist

    if (importAST != nullptr) {
        // cases like android.hardware.foo@1.0::IFoo.Internal
        //        and android.hardware.foo@1.0::IFoo
        if (fqName == interfaceName) {
            // import a single file.
            // all previous single type imports are ignored.
            // cases like android.hardware.foo@1.0::IFoo
            //        and android.hardware.foo@1.0::types
            mImportedTypes.erase(importAST);
            return true;
        }

        // import a single type from this file
        // cases like android.hardware.foo@1.0::IFoo.Internal
        FQName matchingName;
        Type *match = importAST->findDefinedType(fqName, &matchingName);
        if (match == nullptr) {
            return false;
        }
        // will automatically create a set if it does not exist
        mImportedTypes[importAST].insert(match);
        return true;
    }

    // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
    FQName typesFQName = fqName.getTypesForPackage();

    // Do not enforce restrictions on imports.
    importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);

    if (importAST != nullptr) {
        // Attempt to find Abc.Internal in types.
        FQName matchingName;
        Type *match = importAST->findDefinedType(fqName, &matchingName);
        if (match == nullptr) {
            return false;
        }
        // will automatically create a set if not exist
        mImportedTypes[importAST].insert(match);
        return true;
    }

    // can't find an appropriate AST for fqName.
    return false;
}

void AST::addImportedAST(AST *ast) {
    mImportedASTs.insert(ast);
}

FQName AST::makeFullName(const char* localName, Scope* scope) const {
    std::vector<std::string> pathComponents{{localName}};
    for (; scope != &mRootScope; scope = scope->parent()) {
        pathComponents.push_back(scope->localName());
    }

    std::reverse(pathComponents.begin(), pathComponents.end());
    std::string path = StringHelper::JoinStrings(pathComponents, ".");

    return FQName(mPackage.package(), mPackage.version(), path);
}

void AST::addScopedType(NamedType* type, Scope* scope) {
    scope->addType(type);
    mDefinedTypesByFullName[type->fqName()] = type;
}

LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, Scope* scope) {
    const FQName& fqName = ref.getLookupFqName();

    if (fqName.isIdentifier()) {
        LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
        if (iden == nullptr) {
            std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
                      << ref.location() << "\n";
            return nullptr;
        }
        return iden;
    } else {
        std::string errorMsg;
        EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
        if (enumValue == nullptr) {
            std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
            return nullptr;
        }
        return enumValue;
    }
}

EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
    FQName enumTypeName = fqName.typeName();
    std::string enumValueName = fqName.valueName();

    CHECK(enumTypeName.isValid());
    CHECK(!enumValueName.empty());

    Type* type = lookupType(enumTypeName, scope);
    if(type == nullptr) {
        *errorMsg = "Cannot find type " + enumTypeName.string();
        return nullptr;
    }
    type = type->resolve();
    if(!type->isEnum()) {
        *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
        return nullptr;
    }

    EnumType *enumType = static_cast<EnumType *>(type);
    EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
    if(v == nullptr) {
        *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
        return nullptr;
    }

    mReferencedTypeNames.insert(enumType->fqName());

    return v;
}

Type* AST::lookupType(const FQName& fqName, Scope* scope) {
    CHECK(fqName.isValid());

    if (fqName.name().empty()) {
        // Given a package and version???
        return nullptr;
    }

    Type *returnedType = nullptr;

    if (fqName.package().empty() && fqName.version().empty()) {
        // resolve locally first if possible.
        returnedType = lookupTypeLocally(fqName, scope);
        if (returnedType != nullptr) {
            return returnedType;
        }
    }

    status_t status = lookupAutofilledType(fqName, &returnedType);
    if (status != OK) {
        return nullptr;
    }
    if (returnedType != nullptr) {
        return returnedType;
    }

    return lookupTypeFromImports(fqName);
}

// Rule 0: try resolve locally
Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
    CHECK(fqName.package().empty() && fqName.version().empty()
        && !fqName.name().empty() && fqName.valueName().empty());

    for (; scope != nullptr; scope = scope->parent()) {
        Type* type = scope->lookupType(fqName);
        if (type != nullptr) {
            return type;
        }
    }

    return nullptr;
}

// Rule 1: auto-fill with current package
status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
    CHECK(!fqName.name().empty() && fqName.valueName().empty());

    FQName autofilled = fqName;
    autofilled.applyDefaults(mPackage.package(), mPackage.version());
    FQName matchingName;
    // Given this fully-qualified name, the type may be defined in this AST, or other files
    // in import.
    Type *local = findDefinedType(autofilled, &matchingName);
    CHECK(local == nullptr || autofilled == matchingName);
    Type* fromImport = lookupTypeFromImports(autofilled);

    if (local != nullptr && fromImport != nullptr && local != fromImport) {
        // Something bad happen; two types have the same FQName.
        std::cerr << "ERROR: Unable to resolve type name '"
                  << fqName.string()
                  << "' (i.e. '"
                  << autofilled.string()
                  << "'), multiple definitions found.\n";

        return UNKNOWN_ERROR;
    }
    if (local != nullptr) {
        *returnedType = local;
        return OK;
    }
    // If fromImport is nullptr as well, return nullptr to fall through to next rule.
    *returnedType = fromImport;
    return OK;
}

// Rule 2: look at imports
Type *AST::lookupTypeFromImports(const FQName &fqName) {

    Type *resolvedType = nullptr;
    Type *returnedType = nullptr;
    FQName resolvedName;

    for (const auto &importedAST : mImportedASTs) {
        if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
            // ignore single type imports
            continue;
        }
        FQName matchingName;
        Type *match = importedAST->findDefinedType(fqName, &matchingName);

        if (match != nullptr) {
            if (resolvedType != nullptr) {
                std::cerr << "ERROR: Unable to resolve type name '"
                          << fqName.string()
                          << "', multiple matches found:\n";

                std::cerr << "  " << resolvedName.string() << "\n";
                std::cerr << "  " << matchingName.string() << "\n";

                return nullptr;
            }

            resolvedType = match;
            returnedType = resolvedType;
            resolvedName = matchingName;

            // Keep going even after finding a match.
        }
    }

    for (const auto &pair : mImportedTypes) {
        AST *importedAST = pair.first;
        std::set<Type *> importedTypes = pair.second;

        FQName matchingName;
        Type *match = importedAST->findDefinedType(fqName, &matchingName);
        if (match != nullptr &&
                importedTypes.find(match) != importedTypes.end()) {
            if (resolvedType != nullptr) {
                std::cerr << "ERROR: Unable to resolve type name '"
                          << fqName.string()
                          << "', multiple matches found:\n";

                std::cerr << "  " << resolvedName.string() << "\n";
                std::cerr << "  " << matchingName.string() << "\n";

                return nullptr;
            }

            resolvedType = match;
            returnedType = resolvedType;
            resolvedName = matchingName;

            // Keep going even after finding a match.
        }
    }

    if (resolvedType) {
        returnedType = resolvedType;

        // If the resolved type is not an interface, we need to determine
        // whether it is defined in types.hal, or in some other interface.  In
        // the latter case, we need to emit a dependency for the interface in
        // which the type is defined.
        //
        // Consider the following:
        //    android.hardware.tests.foo@1.0::Record
        //    android.hardware.tests.foo@1.0::IFoo.Folder
        //    android.hardware.tests.foo@1.0::Folder
        //
        // If Record is an interface, then we keep track of it for the purpose
        // of emitting dependencies in the target language (for example #include
        // in C++).  If Record is a UDT, then we assume it is defined in
        // types.hal in android.hardware.tests.foo@1.0.
        //
        // In the case of IFoo.Folder, the same applies.  If IFoo is an
        // interface, we need to track this for the purpose of emitting
        // dependencies.  If not, then it must have been defined in types.hal.
        //
        // In the case of just specifying Folder, the resolved type is
        // android.hardware.tests.foo@1.0::Folder, and the same logic as
        // above applies.

        if (!resolvedType->isInterface()) {
            FQName ifc = resolvedName.getTopLevelType();
            for (const auto &importedAST : mImportedASTs) {
                FQName matchingName;
                Type *match = importedAST->findDefinedType(ifc, &matchingName);
                if (match != nullptr && match->isInterface()) {
                    resolvedType = match;
                }
            }
        }

        if (!resolvedType->isInterface()) {
            // Non-interface types are declared in the associated types header.
            FQName typesName = resolvedName.getTypesForPackage();

            mImportedNames.insert(typesName);
        } else {
            // Do _not_ use fqName, i.e. the name we used to look up the type,
            // but instead use the name of the interface we found.
            // This is necessary because if fqName pointed to a typedef which
            // in turn referenced the found interface we'd mistakenly use the
            // name of the typedef instead of the proper name of the interface.

            const FQName &typeName =
                static_cast<Interface *>(resolvedType)->fqName();

            mImportedNames.insert(typeName);
        }
    }

    return returnedType;
}

void AST::addToImportedNamesGranular(const FQName &fqName) {
    if (fqName.package() == package().package()
            && fqName.version() == package().version()) {
        // Our own names are _defined_ here, not imported.
        return;
    }

    mImportedNamesGranular.insert(fqName);
}

Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
    for (const auto &pair : mDefinedTypesByFullName) {
        const FQName &key = pair.first;
        Type* type = pair.second;

        if (key.endsWith(fqName)) {
            *matchingName = key;
            return type;
        }
    }

    return nullptr;
}

void AST::getImportedPackages(std::set<FQName> *importSet) const {
    for (const auto& fqName : mImportedNamesGranular) {
        FQName packageName = fqName.getPackageAndVersion();

        if (packageName == mPackage) {
            // We only care about external imports, not our own package.
            continue;
        }

        importSet->insert(packageName);
    }
}

void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
    getImportedPackages(importSet);

    std::set<FQName> newSet;
    for (const auto &ast : mImportedASTs) {
        if (importSet->find(ast->package()) != importSet->end()) {
            ast->getImportedPackagesHierarchy(&newSet);
        }
    }
    importSet->insert(newSet.begin(), newSet.end());
}

void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
    for (const auto& name : mImportedNames) {
        allImportNames->insert(name);
        AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
        ast->getAllImportedNames(allImportNames);
    }
}

void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
    for (const auto& fqName : mImportedNamesGranular) {
        if (fqName.name() == "types") {
            // A package will export everything _defined_ but will not
            // re-export anything it itself imported.
            AST* ast = mCoordinator->parse(
                    fqName, nullptr /* imported */, Coordinator::Enforce::NONE);

            ast->addDefinedTypes(allImportNames);
        } else {
            allImportNames->insert(fqName);
        }
    }
}

bool AST::isJavaCompatible() const {
    return mRootScope.isJavaCompatible();
}

void AST::appendToExportedTypesVector(
        std::vector<const Type *> *exportedTypes) const {
    mRootScope.appendToExportedTypesVector(exportedTypes);
}

bool AST::isIBase() const {
    Interface* iface = mRootScope.getInterface();
    return iface != nullptr && iface->isIBase();
}

const Interface *AST::getInterface() const {
    return mRootScope.getInterface();
}

std::string AST::getBaseName() const {
    const Interface* iface = mRootScope.getInterface();

    return iface ? iface->getBaseName() : "types";
}

void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
    std::for_each(
            mDefinedTypesByFullName.begin(),
            mDefinedTypesByFullName.end(),
            [definedTypes](const auto &elem) {
                if (!elem.second->isTypeDef()) {
                    definedTypes->insert(elem.first);
                }
            });
}

void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
    std::for_each(
            mReferencedTypeNames.begin(),
            mReferencedTypeNames.end(),
            [referencedTypes](const auto &fqName) {
                referencedTypes->insert(fqName);
            });
}

}  // namespace android;
