/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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.
 */

#pragma once

#include <access/SubjectDescriptor.h>
#include <app/ConcreteAttributePath.h>
#include <app/MessageDef/AttributeReportIBs.h>
#include <app/data-model/DecodableList.h>
#include <app/data-model/Decode.h>
#include <app/data-model/Encode.h>
#include <app/data-model/FabricScoped.h>
#include <app/data-model/List.h> // So we can encode lists
#include <app/data-model/TagBoundEncoder.h>
#include <app/util/basic-types.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/Optional.h>
#include <lib/support/logging/CHIPLogging.h>

/**
 * Callback class that clusters can implement in order to interpose custom
 * attribute-handling logic.  An AttributeAccessInterface instance is associated
 * with some specific cluster.  A single instance may be used for a specific
 * endpoint or for all endpoints.
 *
 * Instances of AttributeAccessInterface that are registered via
 * registerAttributeAccessOverride will be consulted before taking the normal
 * attribute access codepath and can use that codepath as a fallback if desired.
 */
namespace chip {
namespace app {

/**
 * The AttributeReportBuilder is a helper class for filling a single report in AttributeReportIBs.
 *
 * Possible usage of AttributeReportBuilder might be:
 *
 * AttributeReportBuilder builder;
 * ReturnErrorOnFailure(builder.PrepareAttribute(...));
 * ReturnErrorOnFailure(builder.Encode(...));
 * ReturnErrorOnFailure(builder.FinishAttribute());
 */
class AttributeReportBuilder
{
public:
    /**
     * PrepareAttribute encodes the "header" part of an attribute report including the path and data version.
     * Path will be encoded according to section 10.5.4.3.1 in the spec.
     * Note: Only append is supported currently (encode a null list index), other operations won't encode a list index in the
     * attribute path field.
     * TODO: Add support for encoding a single element in the list (path with a valid list index).
     */
    CHIP_ERROR PrepareAttribute(AttributeReportIBs::Builder & aAttributeReportIBs, const ConcreteDataAttributePath & aPath,
                                DataVersion aDataVersion);

    /**
     * FinishAttribute encodes the "footer" part of an attribute report (it closes the containers opened in PrepareAttribute)
     */
    CHIP_ERROR FinishAttribute(AttributeReportIBs::Builder & aAttributeReportIBs);

    /**
     * EncodeValue encodes the value field of the report, it should be called exactly once.
     */
    template <typename T, std::enable_if_t<!DataModel::IsFabricScoped<T>::value, bool> = true, typename... Ts>
    CHIP_ERROR EncodeValue(AttributeReportIBs::Builder & aAttributeReportIBs, T && item, Ts &&... aArgs)
    {
        return DataModel::Encode(*(aAttributeReportIBs.GetAttributeReport().GetAttributeData().GetWriter()),
                                 TLV::ContextTag(to_underlying(AttributeDataIB::Tag::kData)), item, std::forward<Ts>(aArgs)...);
    }

    template <typename T, std::enable_if_t<DataModel::IsFabricScoped<T>::value, bool> = true, typename... Ts>
    CHIP_ERROR EncodeValue(AttributeReportIBs::Builder & aAttributeReportIBs, FabricIndex accessingFabricIndex, T && item,
                           Ts &&... aArgs)
    {
        return DataModel::EncodeForRead(*(aAttributeReportIBs.GetAttributeReport().GetAttributeData().GetWriter()),
                                        TLV::ContextTag(to_underlying(AttributeDataIB::Tag::kData)), accessingFabricIndex, item);
    }
};

/**
 * The AttributeValueEncoder is a helper class for filling report payloads into AttributeReportIBs.
 * The attribute value encoder can be initialized with a AttributeEncodeState for saving and recovering its state between encode
 * sessions (chunkings).
 *
 * When Encode returns recoverable errors (e.g. CHIP_ERROR_NO_MEMORY) the state can be used to initialize the AttributeValueEncoder
 * for future use on the same attribute path.
 */
class AttributeValueEncoder
{
public:
    class ListEncodeHelper
    {
    public:
        ListEncodeHelper(AttributeValueEncoder & encoder) : mAttributeValueEncoder(encoder) {}

        template <typename T, std::enable_if_t<DataModel::IsFabricScoped<T>::value, bool> = true>
        CHIP_ERROR Encode(T && aArg) const
        {
            VerifyOrReturnError(aArg.GetFabricIndex() != kUndefinedFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);

            // If we are encoding for a fabric filtered attribute read and the fabric index does not match that present in the
            // request, skip encoding this list item.
            VerifyOrReturnError(!mAttributeValueEncoder.mIsFabricFiltered ||
                                    aArg.GetFabricIndex() == mAttributeValueEncoder.mAccessingFabricIndex,
                                CHIP_NO_ERROR);
            return mAttributeValueEncoder.EncodeListItem(mAttributeValueEncoder.mAccessingFabricIndex, std::forward<T>(aArg));
        }

        template <typename T, std::enable_if_t<!DataModel::IsFabricScoped<T>::value, bool> = true>
        CHIP_ERROR Encode(T && aArg) const
        {
            return mAttributeValueEncoder.EncodeListItem(std::forward<T>(aArg));
        }

    private:
        AttributeValueEncoder & mAttributeValueEncoder;
    };

    class AttributeEncodeState
    {
    public:
        AttributeEncodeState() : mAllowPartialData(false), mCurrentEncodingListIndex(kInvalidListIndex) {}
        bool AllowPartialData() const { return mAllowPartialData; }

    private:
        friend class AttributeValueEncoder;
        /**
         * When an attempt to encode an attribute returns an error, the buffer may contain tailing dirty data
         * (since the put was aborted).  The report engine normally rolls back the buffer to right before encoding
         * of the attribute started on errors.
         *
         * When chunking a list, EncodeListItem will atomically encode list items, ensuring that the
         * state of the buffer is valid to send (i.e. contains no trailing garbage), and return an error
         * if the list doesn't entirely fit.  In this situation, mAllowPartialData is set to communicate to the
         * report engine that it should not roll back the list items.
         *
         * TODO: There might be a better name for this variable.
         */
        bool mAllowPartialData = false;
        /**
         * If set to kInvalidListIndex, indicates that we have not encoded any data for the list yet and
         * need to start by encoding an empty list before we start encoding any list items.
         *
         * When set to a valid ListIndex value, indicates the index of the next list item that needs to be
         * encoded (i.e. the count of items encoded so far).
         */
        ListIndex mCurrentEncodingListIndex = kInvalidListIndex;
    };

    AttributeValueEncoder(AttributeReportIBs::Builder & aAttributeReportIBsBuilder, FabricIndex aAccessingFabricIndex,
                          const ConcreteAttributePath & aPath, DataVersion aDataVersion, bool aIsFabricFiltered = false,
                          const AttributeEncodeState & aState = AttributeEncodeState()) :
        mAttributeReportIBsBuilder(aAttributeReportIBsBuilder),
        mAccessingFabricIndex(aAccessingFabricIndex), mPath(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId),
        mDataVersion(aDataVersion), mIsFabricFiltered(aIsFabricFiltered), mEncodeState(aState)
    {}

    /**
     * Encode a single value.  This value will not be chunked; it will either be
     * entirely encoded or fail to be encoded.  Consumers are allowed to make
     * either one call to Encode or one call to EncodeList to handle a read.
     */
    template <typename... Ts>
    CHIP_ERROR Encode(Ts &&... aArgs)
    {
        mTriedEncode = true;
        return EncodeAttributeReportIB(std::forward<Ts>(aArgs)...);
    }

    /**
     * Encode an explicit null value.
     */
    CHIP_ERROR EncodeNull()
    {
        // Doesn't matter what type Nullable we use here.
        return Encode(DataModel::Nullable<uint8_t>());
    }

    /**
     * Encode an explicit empty list.
     */
    CHIP_ERROR EncodeEmptyList()
    {
        // Doesn't matter what type List we use here.
        return Encode(DataModel::List<uint8_t>());
    }

    /**
     * aCallback is expected to take a const auto & argument and Encode() on it as many times as needed to encode all the list
     * elements one by one.  If any of those Encode() calls returns failure, aCallback must stop encoding and return failure.  When
     * all items are encoded aCallback is expected to return success.
     *
     * aCallback may not be called.  Consumers must not assume it will be called.
     *
     * When EncodeList returns an error, the consumers must abort the encoding, and return the exact error to the caller.
     *
     * TODO: Can we hold a error state in the AttributeValueEncoder itself so functions in ember-compatibility-functions don't have
     * to rely on the above assumption?
     *
     * Consumers are allowed to make either one call to EncodeList or one call to Encode to handle a read.
     *
     */
    template <typename ListGenerator>
    CHIP_ERROR EncodeList(ListGenerator aCallback)
    {
        mTriedEncode = true;
        // Spec 10.5.4.3.1, 10.5.4.6 (Replace a list w/ Multiple IBs)
        // EmptyList acts as the beginning of the whole array type attribute report.
        // An empty list is encoded iff both mCurrentEncodingListIndex and mEncodeState.mCurrentEncodingListIndex are invalid
        // values. After encoding the empty list, mEncodeState.mCurrentEncodingListIndex and mCurrentEncodingListIndex are set to 0.
        ReturnErrorOnFailure(EnsureListStarted());
        ReturnErrorOnFailure(aCallback(ListEncodeHelper(*this)));
        // The Encode procedure finished without any error, clear the state.
        mEncodeState = AttributeEncodeState();
        return CHIP_NO_ERROR;
    }

    bool TriedEncode() const { return mTriedEncode; }

    /**
     * The accessing fabric index for this read or subscribe interaction.
     */
    FabricIndex AccessingFabricIndex() const { return mAccessingFabricIndex; }

    /**
     * AttributeValueEncoder is a short lived object, and the state is persisted by mEncodeState and restored by constructor.
     */
    const AttributeEncodeState & GetState() const { return mEncodeState; }

private:
    // We made EncodeListItem() private, and ListEncoderHelper will expose it by Encode()
    friend class ListEncodeHelper;

    template <typename... Ts>
    CHIP_ERROR EncodeListItem(Ts &&... aArgs)
    {
        // EncodeListItem must be called after EnsureListStarted(), thus mCurrentEncodingListIndex and
        // mEncodeState.mCurrentEncodingListIndex are not invalid values.
        if (mCurrentEncodingListIndex < mEncodeState.mCurrentEncodingListIndex)
        {
            // We have encoded this element in previous chunks, skip it.
            mCurrentEncodingListIndex++;
            return CHIP_NO_ERROR;
        }

        TLV::TLVWriter backup;
        mAttributeReportIBsBuilder.Checkpoint(backup);

        CHIP_ERROR err = EncodeAttributeReportIB(std::forward<Ts>(aArgs)...);
        if (err != CHIP_NO_ERROR)
        {
            // For list chunking, ReportEngine should not rollback the buffer when CHIP_ERROR_NO_MEMORY or similar error occurred.
            // However, the error might be raised in the middle of encoding procedure, then the buffer may contain partial data,
            // unclosed containers etc. This line clears all possible partial data and makes EncodeListItem is atomic.
            mAttributeReportIBsBuilder.Rollback(backup);
            return err;
        }

        mCurrentEncodingListIndex++;
        mEncodeState.mCurrentEncodingListIndex++;
        return CHIP_NO_ERROR;
    }

    /**
     * Builds a single AttributeReportIB in AttributeReportIBs.  The caller is
     * responsible for setting up mPath correctly.
     *
     * In particular, when we are encoding a single element in the list, mPath
     * must indicate a null list index to represent an "append" operation.
     * operation.
     */
    template <typename... Ts>
    CHIP_ERROR EncodeAttributeReportIB(Ts &&... aArgs)
    {
        AttributeReportBuilder builder;

        ReturnErrorOnFailure(builder.PrepareAttribute(mAttributeReportIBsBuilder, mPath, mDataVersion));
        ReturnErrorOnFailure(builder.EncodeValue(mAttributeReportIBsBuilder, std::forward<Ts>(aArgs)...));

        return builder.FinishAttribute(mAttributeReportIBsBuilder);
    }

    /**
     * EnsureListStarted encodes the first item of one report with lists (an
     * empty list), as needed.
     *
     * If internal state indicates we have already encoded the empty list, this function will encode nothing, set
     * mCurrentEncodingListIndex to 0 and return CHIP_NO_ERROR.
     *
     * In all cases this function guarantees that mPath.mListOp is AppendItem
     * after it returns, because at that point we will be encoding the list
     * items.
     */
    CHIP_ERROR EnsureListStarted();

    bool mTriedEncode = false;
    AttributeReportIBs::Builder & mAttributeReportIBsBuilder;
    const FabricIndex mAccessingFabricIndex;
    ConcreteDataAttributePath mPath;
    DataVersion mDataVersion;
    bool mIsFabricFiltered = false;
    AttributeEncodeState mEncodeState;
    ListIndex mCurrentEncodingListIndex = kInvalidListIndex;
};

class AttributeValueDecoder
{
public:
    AttributeValueDecoder(TLV::TLVReader & aReader, const Access::SubjectDescriptor & aSubjectDescriptor) :
        mReader(aReader), mSubjectDescriptor(aSubjectDescriptor)
    {}

    template <typename T, typename std::enable_if_t<!DataModel::IsFabricScoped<T>::value, bool> = true>
    CHIP_ERROR Decode(T & aArg)
    {
        mTriedDecode = true;
        return DataModel::Decode(mReader, aArg);
    }

    template <typename T, typename std::enable_if_t<DataModel::IsFabricScoped<T>::value, bool> = true>
    CHIP_ERROR Decode(T & aArg)
    {
        mTriedDecode = true;
        // The WriteRequest comes with no fabric index, this will happen when receiving a write request on a PASE session before
        // AddNOC.
        VerifyOrReturnError(AccessingFabricIndex() != kUndefinedFabricIndex, CHIP_IM_GLOBAL_STATUS(UnsupportedAccess));
        ReturnErrorOnFailure(DataModel::Decode(mReader, aArg));
        aArg.SetFabricIndex(AccessingFabricIndex());
        return CHIP_NO_ERROR;
    }

    /**
     * Is the next element of the stream NULL.
     */
    bool WillDecodeNull() const { return mReader.GetType() == TLV::kTLVType_Null; }

    bool TriedDecode() const { return mTriedDecode; }

    /**
     * The accessing fabric index for this write interaction.
     */
    FabricIndex AccessingFabricIndex() const { return mSubjectDescriptor.fabricIndex; }

    /**
     * The accessing subject descriptor for this write interaction.
     */
    const Access::SubjectDescriptor & GetSubjectDescriptor() const { return mSubjectDescriptor; }

private:
    TLV::TLVReader & mReader;
    bool mTriedDecode = false;
    const Access::SubjectDescriptor mSubjectDescriptor;
};

class AttributeAccessInterface
{
public:
    /**
     * aEndpointId can be Missing to indicate that this object is meant to be
     * used with all endpoints.
     */
    AttributeAccessInterface(Optional<EndpointId> aEndpointId, ClusterId aClusterId) :
        mEndpointId(aEndpointId), mClusterId(aClusterId)
    {}
    virtual ~AttributeAccessInterface() {}

    /**
     * Callback for reading attributes.
     *
     * @param [in] aPath indicates which exact data is being read.
     * @param [in] aEncoder the AttributeValueEncoder to use for encoding the
     *             data.
     *
     * The implementation can do one of three things:
     *
     * 1) Return a failure.  This is treated as a failed read and the error is
     *    returned to the client, by converting it to a StatusIB.
     * 2) Return success and attempt to encode data using aEncoder.  The data is
     *    returned to the client.
     * 3) Return success and not attempt to encode any data using aEncoder.  In
     *    this case, Ember attribute access will happen for the read. This may
     *    involve reading from the attribute store or external attribute
     *    callbacks.
     */
    virtual CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) = 0;

    /**
     * Callback for writing attributes.
     *
     * @param [in] aPath indicates which exact data is being written.
     * @param [in] aDecoder the AttributeValueDecoder to use for decoding the
     *             data.
     *
     * The implementation can do one of three things:
     *
     * 1) Return a failure.  This is treated as a failed write and the error is
     *    sent to the client, by converting it to a StatusIB.
     * 2) Return success and attempt to decode from aDecoder.  This is
     *    treated as a successful write.
     * 3) Return success and not attempt to decode from aDecoder.  In
     *    this case, Ember attribute access will happen for the write. This may
     *    involve writing to the attribute store or external attribute
     *    callbacks.
     */
    virtual CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) { return CHIP_NO_ERROR; }

    /**
     * Indicates the start of a series of list operations. This function will be called before the first Write operation of a series
     * of consequence attribute data of the same attribute.
     *
     * 1) This function will be called if the client tries to set a nullable list attribute to null.
     * 2) This function will only be called once for a series of consequent attribute data (regardless the kind of list operation)
     * of the same attribute.
     *
     * @param [in] aPath indicates the path of the modified list.
     */
    virtual void OnListWriteBegin(const ConcreteAttributePath & aPath) {}

    /**
     * Indicates the end of a series of list operations. This function will be called after the last Write operation of a series
     * of consequence attribute data of the same attribute.
     *
     * 1) This function will be called if the client tries to set a nullable list attribute to null.
     * 2) This function will only be called once for a series of consequent attribute data (regardless the kind of list operation)
     * of the same attribute.
     * 3) When aWriteWasSuccessful is true, the data written must be consistent or the list is untouched.
     *
     * @param [in] aPath indicates the path of the modified list
     * @param [in] aWriteWasSuccessful indicates whether the delivered list is complete.
     *
     */
    virtual void OnListWriteEnd(const ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {}

    /**
     * Mechanism for keeping track of a chain of AttributeAccessInterfaces.
     */
    void SetNext(AttributeAccessInterface * aNext) { mNext = aNext; }
    AttributeAccessInterface * GetNext() const { return mNext; }

    /**
     * Check whether a this AttributeAccessInterface is relevant for a
     * particular endpoint+cluster.  An AttributeAccessInterface will be used
     * for a read from a particular cluster only when this function returns
     * true.
     */
    bool Matches(EndpointId aEndpointId, ClusterId aClusterId) const
    {
        return (!mEndpointId.HasValue() || mEndpointId.Value() == aEndpointId) && mClusterId == aClusterId;
    }

    /**
     * Check whether an AttributeAccessInterface is relevant for a particular
     * specific endpoint.  This is used to clean up overrides registered for an
     * endpoint that becomes disabled.
     */
    bool MatchesEndpoint(EndpointId aEndpointId) const { return mEndpointId.HasValue() && mEndpointId.Value() == aEndpointId; }

    /**
     * Check whether another AttributeAccessInterface wants to handle the same set of
     * attributes as we do.
     */
    bool Matches(const AttributeAccessInterface & aOther) const
    {
        return mClusterId == aOther.mClusterId &&
            (!mEndpointId.HasValue() || !aOther.mEndpointId.HasValue() || mEndpointId.Value() == aOther.mEndpointId.Value());
    }

private:
    Optional<EndpointId> mEndpointId;
    ClusterId mClusterId;
    AttributeAccessInterface * mNext = nullptr;
};

} // namespace app
} // namespace chip
