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

#define INTERFACE_H_

#include <string>
#include <vector>

#include <hidl-hash/Hash.h>

#include "ConstantExpression.h"
#include "Reference.h"
#include "Scope.h"

namespace android {

struct Method;
struct InterfaceAndMethod;

extern const FQName gIBaseFqName;
extern const FQName gIManagerFqName;

struct Interface : public Scope {
    const static std::unique_ptr<ConstantExpression> FLAG_ONE_WAY;
    const static std::unique_ptr<ConstantExpression> FLAG_CLEAR_BUF;

    Interface(const std::string& localName, const FQName& fullName, const Location& location,
              Scope* parent, const Reference<Type>& superType, const Hash* fileHash);

    const Hash* getFileHash() const;

    void addUserDefinedMethod(Method* method);
    bool addAllReservedMethods(const std::map<std::string, Method*>& allReservedMethods);

    bool isElidableType() const override;
    bool isInterface() const override;
    bool isIBase() const { return fqName() == gIBaseFqName; }
    std::string typeName() const override;

    bool hasSensitiveDataAnnotation() const;

    const Interface* superType() const;

    // Super type chain to root type.
    // First element is superType().
    std::vector<const Interface *> superTypeChain() const;
    // Super type chain to root type, including myself.
    // First element is this.
    std::vector<const Interface *> typeChain() const;

    // user defined methods (explicit definition in HAL files)
    const std::vector<Method *> &userDefinedMethods() const;
    // HIDL reserved methods (every interface has these implicitly defined)
    const std::vector<Method *> &hidlReservedMethods() const;
    // the sum of userDefinedMethods() and hidlReservedMethods().
    std::vector<Method *> methods() const;

    // userDefinedMethods() for all super type + methods()
    // The order will be as follows (in the transaction code order):
    // great-great-...-great-grand parent->userDefinedMethods()
    // ...
    // parent->userDefinedMethods()
    // this->userDefinedMethods()
    // this->hidlReservedMethods()
    std::vector<InterfaceAndMethod> allMethodsFromRoot() const;

    // allMethodsFromRoot for parent
    std::vector<InterfaceAndMethod> allSuperMethodsFromRoot() const;

    // aliases for corresponding methods in this->fqName()
    std::string getBaseName() const;
    std::string getProxyName() const;
    std::string getStubName() const;
    std::string getPassthroughName() const;
    std::string getHwName() const;
    FQName getProxyFqName() const;
    FQName getStubFqName() const;
    FQName getPassthroughFqName() const;

    std::string getCppType(
            StorageMode mode,
            bool specifyNamespaces) const override;

    std::string getJavaType(bool forInitializer) const override;
    std::string getVtsType() const override;

    std::vector<const Reference<Type>*> getReferences() const override;
    std::vector<const Reference<Type>*> getStrongReferences() const override;

    status_t resolveInheritance() override;
    status_t validate() const override;
    status_t validateUniqueNames() const;
    status_t validateAnnotations() const override;

    void emitReaderWriter(
            Formatter &out,
            const std::string &name,
            const std::string &parcelObj,
            bool parcelObjIsPointer,
            bool isReader,
            ErrorMode mode) const override;

    void emitHidlDefinition(Formatter& out) const override;

    void emitPackageTypeDeclarations(Formatter& out) const override;
    void emitPackageTypeHeaderDefinitions(Formatter& out) const override;
    void emitTypeDefinitions(Formatter& out, const std::string& prefix) const override;

    void getAlignmentAndSize(size_t* align, size_t* size) const override;
    void emitJavaReaderWriter(
            Formatter &out,
            const std::string &parcelObj,
            const std::string &argName,
            bool isReader) const override;

    void emitVtsAttributeType(Formatter& out) const override;

    void emitVtsAttributeDeclaration(Formatter& out) const;
    void emitVtsMethodDeclaration(Formatter& out, bool isInherited) const;

    bool deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const override;

    bool isNeverStrongReference() const override;

   private:
    Reference<Type> mSuperType;

    std::vector<Method*> mUserMethods;
    std::vector<Method*> mReservedMethods;

    const Hash* mFileHash;

    bool fillPingMethod(Method* method) const;
    bool fillDescriptorChainMethod(Method* method) const;
    bool fillGetDescriptorMethod(Method* method) const;
    bool fillHashChainMethod(Method* method) const;
    bool fillSyspropsChangedMethod(Method* method) const;
    bool fillLinkToDeathMethod(Method* method) const;
    bool fillUnlinkToDeathMethod(Method* method) const;
    bool fillSetHALInstrumentationMethod(Method* method) const;
    bool fillGetDebugInfoMethod(Method* method) const;
    bool fillDebugMethod(Method* method) const;

    void emitDigestChain(
        Formatter& out, const std::string& prefix, const std::vector<const Interface*>& chain,
        std::function<std::string(std::unique_ptr<ConstantExpression>)> byteToString) const;

    DISALLOW_COPY_AND_ASSIGN(Interface);
};

// An interface / method tuple.
struct InterfaceAndMethod {
    InterfaceAndMethod(const Interface *iface, Method *method)
        : mInterface(iface),
          mMethod(method) {}
    Method *method() const { return mMethod; }
    const Interface *interface() const { return mInterface; }

   private:
    // do not own these objects.
    const Interface *mInterface;
    Method *mMethod;
};

}  // namespace android

#endif  // INTERFACE_H_

