/*
 * 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 EnumValue;
struct Formatter;
struct Interface;
struct Location;
struct Method;
struct NamedType;
template <class T>
struct NamedReference;
struct Type;

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

    bool setPackage(const char *package);
    bool addImport(const char *import);

    // package and version really.
    FQName package() const;
    bool isInterface() const;
    bool containsInterfaces() 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;

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

    // Look up an enum value by "FQName:valueName".
    EnumValue* lookupEnumValue(const FQName& fqName, std::string* errorMsg, 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, 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);

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

    // Recursive tree pass that looks up all referenced local identifiers
    status_t lookupLocalIdentifiers();

    // 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 evaluates constant expressions
    status_t evaluate();

    // 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 generateCppAdapterHeader(Formatter& out) const;
    void generateCppAdapterSource(Formatter& out) const;

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

    void generateVts(Formatter& out) 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* getRootScope();

    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);

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

    RootScope mRootScope;

    FQName mPackage;

    // 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;

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

    std::set<FQName> mReferencedTypeNames;

    // Helper functions for lookupType.
    Type* lookupTypeLocally(const FQName& fqName, 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;

    void getPackageComponents(std::vector<std::string> *components) const;

    void getPackageAndVersionComponents(
            std::vector<std::string> *components, bool cpp_compatible) const;

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

    static void generateCheckNonNull(Formatter &out, const std::string &nonNull);

    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;
    void generateStaticProxyMethodSource(Formatter& out, const std::string& className,
                                         const Method* method) const;
    void generateProxyMethodSource(Formatter& out, const std::string& className,
                                   const Method* method, const Interface* superInterface) const;
    void generateAdapterMethod(Formatter& out, const Method* method) 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;

    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;

    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 emitCppResolveReferences(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 emitTypeDeclarations(Formatter& out) const;
    void emitJavaTypeDeclarations(Formatter& out) const;
    void emitVtsTypeDeclarations(Formatter& out) const;

    DISALLOW_COPY_AND_ASSIGN(AST);
};

}  // namespace android

#endif  // AST_H_
