/*
 * 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.
 */

#ifndef AST_H_

#define AST_H_

#include <android-base/macros.h>
#include <hidl-hash/Hash.h>
#include <hidl-util/FQName.h>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "Scope.h"
#include "Type.h"

namespace android {

struct Coordinator;
struct ConstantExpression;
struct DocComment;
struct EnumValue;
struct Formatter;
struct Interface;
struct Location;
struct Method;
struct NamedType;
template <class T>
struct NamedReference;
struct Type;

struct ImportStatement {
    FQName fqName;
    Location location;
};

struct AST {
    AST(const Coordinator* coordinator, const Hash* fileHash);

    bool setPackage(const char *package);
    bool addImport(const char* import, const Location& location);
    bool addImplicitImport(const FQName& fqName);

    // package and version really.
    FQName package() const;
    bool isInterface() const;
    bool definesInterfaces() const;

    // Adds package, version and scope stack to local name
    FQName makeFullName(const char* localName, Scope* scope) const;

    void addScopedType(NamedType* type, Scope* scope);

    const std::string& getFilename() const;
    const Hash* getFileHash() const;

    const Coordinator& getCoordinator() const;

    // Look up local identifier.
    // It could be plain identifier or enum value as described by lookupEnumValue.
    LocalIdentifier* lookupLocalIdentifier(const Reference<LocalIdentifier>& ref,
                                           const Scope* scope);

    // Look up an enum value by "FQName:valueName".
    EnumValue* lookupEnumValue(const FQName& fqName, std::string* errorMsg, const Scope* scope);

    // Look up a type by FQName, "pure" names, i.e. those without package
    // or version are first looked up in the current scope chain.
    // After that lookup proceeds to imports.
    Type* lookupType(const FQName& fqName, const Scope* scope);

    void addImportedAST(AST *ast);

    // Calls all passes after parsing required before
    // being ready to generate output.
    status_t postParse();

    // Recursive pass on constant expression tree
    status_t constantExpressionRecursivePass(
        const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies);
    status_t constantExpressionRecursivePass(
        const std::function<status_t(const ConstantExpression*)>& func,
        bool processBeforeDependencies) const;

    // Recursive tree pass that sets ParseStage of all types to newStage.
    status_t setParseStage(Type::ParseStage oldStage, Type::ParseStage newStage);

    // Recursive tree pass that looks up all referenced types
    status_t lookupTypes();

    // Recursive tree pass that looks up all referenced local identifiers
    // and types referenced by constant expressions
    status_t lookupConstantExpressions();

    // Recursive tree pass that validates that all defined types
    // have unique names in their scopes.
    status_t validateDefinedTypesUniqueNames() const;

    // Recursive tree pass that completes type declarations
    // that depend on super types
    status_t resolveInheritance();

    // Recursive tree pass that validates constant expressions
    status_t validateConstantExpressions() const;

    // Recursive tree pass that evaluates constant expressions
    status_t evaluateConstantExpressions();

    // Recursive tree pass that validates all type-related
    // syntax restrictions
    status_t validate() const;

    // Recursive tree pass that ensures that type definitions and references
    // are acyclic and reorderes type definitions in reversed topological order.
    status_t topologicalReorder();

    // Recursive tree pass that ensures that constant expressions
    // are acyclic.
    status_t checkAcyclicConstantExpressions() const;

    // Recursive tree pass that checks C++ forward declaration restrictions.
    status_t checkForwardReferenceRestrictions() const;

    status_t gatherReferencedTypes();

    void generateCppSource(Formatter& out) const;

    void generateInterfaceHeader(Formatter& out) const;
    void generateHwBinderHeader(Formatter& out) const;
    void generateStubHeader(Formatter& out) const;
    void generateProxyHeader(Formatter& out) const;
    void generatePassthroughHeader(Formatter& out) const;

    void generateCppImplHeader(Formatter& out) const;
    void generateCppImplSource(Formatter& out) const;

    void generateJava(Formatter& out, const std::string& limitToType) const;
    void generateJavaImpl(Formatter& out) const;
    void generateJavaTypes(Formatter& out, const std::string& limitToType) const;

    void generateVts(Formatter& out) const;

    void generateDependencies(Formatter& out) const;
    void generateInheritanceHierarchy(Formatter& out) const;

    void generateFormattedHidl(Formatter& out) const;

    const std::vector<ImportStatement>& getImportStatements() const;
    void getImportedPackages(std::set<FQName> *importSet) const;

    // Run getImportedPackages on this, then run getImportedPackages on
    // each AST in each package referenced in importSet.
    void getImportedPackagesHierarchy(std::set<FQName> *importSet) const;

    bool isJavaCompatible() const;

    // Warning: this only includes names explicitly referenced in code.
    //   It does not include all names which are imported.
    //
    // Currently, there is one valid usecase for this: importing exactly
    // the names which need to be imported in generated code. If you import
    // based on getAllImportedNamesGranular instead, you will import things
    // that aren't actually used in the resultant code.
    //
    // Get transitive closure of imported interface/types. This will add
    // everything exported by a package even if only a single type from
    // that package was explicitly imported!
    void getAllImportedNames(std::set<FQName> *allImportSet) const;

    // Get imported types, this includes those explicitly imported as well
    // as all types defined in imported packages.
    void getAllImportedNamesGranular(std::set<FQName> *allImportSet) const;

    void appendToExportedTypesVector(
            std::vector<const Type *> *exportedTypes) const;

    // used by the parser.
    void addSyntaxError();
    size_t syntaxErrors() const;

    bool isIBase() const;

    // or nullptr if not isInterface
    const Interface *getInterface() const;

    // types or Interface base name (e.x. Foo)
    std::string getBaseName() const;

    Scope* getMutableRootScope();
    const Scope& getRootScope() const;

    static void generateCppPackageInclude(Formatter& out, const FQName& package,
                                          const std::string& klass);

    void addDefinedTypes(std::set<FQName> *definedTypes) const;
    void addReferencedTypes(std::set<FQName> *referencedTypes) const;

    void addToImportedNamesGranular(const FQName &fqName);

    bool addMethod(Method* method, Interface* iface);
    bool addAllReservedMethodsToInterface(Interface* iface);

    void setHeader(const DocComment* header);
    const DocComment* getHeader() const;

    // TODO: Clean up all interface usages of unhandled comments and ensure they are attached to the
    // right element
    void addUnhandledComment(const DocComment* docComment);
    const std::vector<const DocComment*> getUnhandledComments() const;

  private:
    const Coordinator* mCoordinator;
    const Hash* mFileHash;

    RootScope mRootScope;

    FQName mPackage;

    // Header for the file
    const DocComment* mHeader = nullptr;

    // A list of trailing DocComments.
    std::vector<const DocComment*> mUnhandledComments;

    // A list of the FQNames present in the import statements
    std::vector<ImportStatement> mImportStatements;

    // A list of FQNames that are imported implicitly
    std::vector<FQName> mImplicitImports;

    // A set of all external interfaces/types that are _actually_ referenced
    // in this AST, this is a subset of those specified in import statements.
    // Note that this set only resolves to the granularity of either an
    // interface type or a whole package.
    std::set<FQName> mImportedNames;

    // This is the set of actually imported types.
    std::set<FQName> mImportedNamesGranular;

    // Warning: this only includes names explicitly referenced in code.
    //   It does not include all names which are imported.
    //
    // A set of all ASTs we explicitly or implicitly (types.hal) import.
    std::set<AST *> mImportedASTs;

    // If a single type (instead of the whole AST) is imported, the AST will be
    // present as a key to this map, with the value being a list of types
    // imported from this AST. If an AST appears in mImportedASTs but not in
    // mImportedTypes, then the whole AST is imported.
    std::map<AST *, std::set<Type *>> mImportedTypes;

    // Types keyed by full names defined in this AST.
    std::map<FQName, Type *> mDefinedTypesByFullName;

    // contains all the hidl reserved methods part of this AST
    std::map<std::string, Method*> mAllReservedMethods;

    // used by the parser.
    size_t mSyntaxErrors = 0;

    std::set<FQName> mReferencedTypeNames;

    // importFQName will try to import fqName by parsing any file that might contain it
    bool importFQName(const FQName& fqName);

    // Helper functions for lookupType.
    Type* lookupTypeLocally(const FQName& fqName, const Scope* scope);
    status_t lookupAutofilledType(const FQName &fqName, Type **returnedType);
    Type *lookupTypeFromImports(const FQName &fqName);

    // Find a type matching fqName (which may be partial) and if found
    // return the associated type and fill in the full "matchingName".
    // Only types defined in this very AST are considered.
    Type *findDefinedType(const FQName &fqName, FQName *matchingName) const;

    std::string makeHeaderGuard(const std::string &baseName,
                                bool indicateGenerated = true) const;
    void enterLeaveNamespace(Formatter &out, bool enter) const;

    void generateTypeSource(Formatter& out, const std::string& ifaceName) const;

    // a method, and in which interface is it originally defined.
    // be careful of the case where method.isHidlReserved(), where interface
    // is effectively useless.
    using MethodGenerator = std::function<void(const Method*, const Interface*)>;

    void generateTemplatizationLink(Formatter& out) const;
    void generateCppTag(Formatter& out, const std::string& tag) const;

    void generateMethods(Formatter& out, const MethodGenerator& gen,
                         bool includeParents = true) const;
    void generateStubImplMethod(Formatter& out, const std::string& className,
                                const Method* method) const;
    void generatePassthroughMethod(Formatter& out, const Method* method, const Interface* superInterface) const;
    void generateStaticProxyMethodSource(Formatter& out, const std::string& className,
                                         const Method* method, const Interface* superInterface) const;
    void generateProxyMethodSource(Formatter& out, const std::string& className,
                                   const Method* method, const Interface* superInterface) const;
    void generateFetchSymbol(Formatter &out, const std::string &ifaceName) const;

    void generateProxySource(Formatter& out, const FQName& fqName) const;

    void generateStubSource(Formatter& out, const Interface* iface) const;

    void generateStubSourceForMethod(Formatter& out, const Method* method,
                                     const Interface* superInterface) const;
    void generateStaticStubMethodSource(Formatter& out, const FQName& fqName,
                                        const Method* method, const Interface* superInterface) const;

    void generatePassthroughSource(Formatter& out) const;

    void generateInterfaceSource(Formatter& out) const;

    enum InstrumentationEvent {
        SERVER_API_ENTRY = 0,
        SERVER_API_EXIT,
        CLIENT_API_ENTRY,
        CLIENT_API_EXIT,
        SYNC_CALLBACK_ENTRY,
        SYNC_CALLBACK_EXIT,
        ASYNC_CALLBACK_ENTRY,
        ASYNC_CALLBACK_EXIT,
        PASSTHROUGH_ENTRY,
        PASSTHROUGH_EXIT,
    };

    void generateCppAtraceCall(
            Formatter &out,
            InstrumentationEvent event,
            const Method *method) const;

    void generateCppInstrumentationCall(
            Formatter &out,
            InstrumentationEvent event,
            const Method *method,
            const Interface* superInterface) const;

    void declareCppReaderLocals(Formatter& out, const std::vector<NamedReference<Type>*>& arg,
                                bool forResults) const;

    void emitCppReaderWriter(Formatter& out, const std::string& parcelObj, bool parcelObjIsPointer,
                             const NamedReference<Type>* arg, bool isReader, Type::ErrorMode mode,
                             bool addPrefixToName) const;

    void emitJavaReaderWriter(Formatter& out, const std::string& parcelObj,
                              const NamedReference<Type>* arg, bool isReader,
                              bool addPrefixToName) const;

    void emitVtsTypeDeclarations(Formatter& out) const;

    DISALLOW_COPY_AND_ASSIGN(AST);
};

}  // namespace android

#endif  // AST_H_
