/*
 *    Copyright (c) 2021-2024 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/AttributeEncodeState.h>
#include <app/AttributeReportBuilder.h>
#include <app/ConcreteAttributePath.h>
#include <app/MessageDef/AttributeReportIBs.h>
#include <app/data-model/FabricScoped.h>
#include <app/data-model/List.h>
#include <lib/support/BitFlags.h>
#include <lib/support/BitMask.h>

#include <type_traits>

namespace chip {
namespace app {

/**
 * 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
{
private:
    // Attempt to save flash by reducing the number of instantiations of the
    // Encode methods for AttributeValueEncoder and ListEncodeHelper.  The idea
    // here is that some types actually end up encoded as other types anyway
    // (e.g. all integers are encoded are uint64_t or int64_t), so we might as
    // well avoid generating template instantiations of our methods (which have
    // extra logic) for all the different types that end up encoded the same in
    // the end.
    //
    // A type is a "base" type if it can't be treated as any other type for
    // encoding purposes.  Overloads of BaseEncodableValue can be added for
    // "non-base" types to return values of a base type.
    //
    // It's important here to not collapse together types for which
    // DataModel::Encode in fact has different behavior (e.g. enum types).
    template <typename T>
    static constexpr const T & BaseEncodableValue(const T & aArg)
    {
        return aArg;
    }
    template <typename T>
    static constexpr auto BaseEncodableValue(const BitFlags<T> & aArg)
    {
        return BaseEncodableValue(aArg.Raw());
    }
    template <typename T>
    static constexpr auto BaseEncodableValue(const BitMask<T> & aArg)
    {
        return BaseEncodableValue(aArg.Raw());
    }
    static constexpr uint64_t BaseEncodableValue(uint32_t aArg) { return aArg; }
    static constexpr uint64_t BaseEncodableValue(uint16_t aArg) { return aArg; }
    static constexpr uint64_t BaseEncodableValue(uint8_t aArg) { return aArg; }
    static constexpr int64_t BaseEncodableValue(int32_t aArg) { return aArg; }
    static constexpr int64_t BaseEncodableValue(int16_t aArg) { return aArg; }
    static constexpr int64_t BaseEncodableValue(int8_t aArg) { return aArg; }

    // Determines whether a type should be encoded as-is (if IsBaseType<T> is
    // true) or transformed to a different type by calling BaseEncodableValue()
    // on it.
    template <typename T>
    static constexpr bool IsBaseType = std::is_same_v<const T &, decltype(BaseEncodableValue(std::declval<const T &>()))>;

public:
    class ListEncodeHelper
    {
    public:
        ListEncodeHelper(AttributeValueEncoder & encoder) : mAttributeValueEncoder(encoder) {}

        template <typename T, std::enable_if_t<IsBaseType<T> && DataModel::IsFabricScoped<T>::value, bool> = true>
        CHIP_ERROR Encode(const 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.AccessingFabricIndex(),
                                CHIP_NO_ERROR);
            return mAttributeValueEncoder.EncodeListItem(mCheckpoint, aArg, mAttributeValueEncoder.AccessingFabricIndex());
        }

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

        template <typename T, std::enable_if_t<!IsBaseType<T>, bool> = true>
        CHIP_ERROR Encode(const T & aArg) const
        {
            return Encode(BaseEncodableValue(aArg));
        }

    private:
        AttributeValueEncoder & mAttributeValueEncoder;
        // Avoid calling the TLVWriter constructor for every instantiation of
        // EncodeListItem.  We treat encoding as a const operation, so either
        // have to put this on the stack (in which case it's per-instantiation),
        // or have it as mutable state.
        mutable TLV::TLVWriter mCheckpoint;
    };

    AttributeValueEncoder(AttributeReportIBs::Builder & aAttributeReportIBsBuilder, Access::SubjectDescriptor subjectDescriptor,
                          const ConcreteAttributePath & aPath, DataVersion aDataVersion, bool aIsFabricFiltered = false,
                          const AttributeEncodeState & aState = AttributeEncodeState()) :
        mAttributeReportIBsBuilder(aAttributeReportIBsBuilder),
        mSubjectDescriptor(subjectDescriptor), 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 T, std::enable_if_t<IsBaseType<T>, bool> = true>
    CHIP_ERROR Encode(const T & aArg)
    {
        mTriedEncode = true;
        return EncodeAttributeReportIB(aArg);
    }

    template <typename T, std::enable_if_t<!IsBaseType<T>, bool> = true>
    CHIP_ERROR Encode(const T & aArg)
    {
        return Encode(BaseEncodableValue(aArg));
    }

    /**
     * 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?
     *
     * 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());
        CHIP_ERROR err = aCallback(ListEncodeHelper(*this));

        // Even if encoding list items failed, make sure we EnsureListEnded().
        // Since we encode list items atomically, in the case when we just
        // didn't fit the next item we want to make sure our list is properly
        // ended before the reporting engine starts chunking.
        EnsureListEnded();
        if (err == CHIP_NO_ERROR)
        {
            // The Encode procedure finished without any error, clear the state.
            mEncodeState.Reset();
        }
        return err;
    }

    bool TriedEncode() const { return mTriedEncode; }

    const Access::SubjectDescriptor & GetSubjectDescriptor() const { return mSubjectDescriptor; }

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

    /**
     * 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;
    friend class TestOnlyAttributeValueEncoderAccessor;

    // Returns true if the list item should be encoded.  If it should, the
    // passed-in TLVWriter will be used to checkpoint the current state of our
    // attribute report list builder.
    bool ShouldEncodeListItem(TLV::TLVWriter & aCheckpoint);

    // Does any cleanup work needed after attempting to encode a list item.
    void PostEncodeListItem(CHIP_ERROR aEncodeStatus, const TLV::TLVWriter & aCheckpoint);

    // EncodeListItem may be given an extra FabricIndex argument as a second
    // arg, or not.  Represent that via a parameter pack (which might be
    // empty). In practice, for any given ItemType the extra arg is either there
    // or not, so we don't get more template explosion due to aExtraArgs.
    template <typename ItemType, typename... ExtraArgTypes>
    CHIP_ERROR EncodeListItem(TLV::TLVWriter & aCheckpoint, const ItemType & aItem, ExtraArgTypes &&... aExtraArgs)
    {
        if (!ShouldEncodeListItem(aCheckpoint))
        {
            return CHIP_NO_ERROR;
        }

        CHIP_ERROR err;
        if (mEncodingInitialList)
        {
            // Just encode a single item, with an anonymous tag.
            AttributeReportBuilder builder;
            err = builder.EncodeValue(mAttributeReportIBsBuilder, TLV::AnonymousTag(), aItem,
                                      std::forward<ExtraArgTypes>(aExtraArgs)...);
        }
        else
        {
            err = EncodeAttributeReportIB(aItem, std::forward<ExtraArgTypes>(aExtraArgs)...);
        }

        PostEncodeListItem(err, aCheckpoint);
        return err;
    }

    /**
     * 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.
     *
     * EncodeAttributeReportIB may be given an extra FabricIndex argument as a second
     * arg, or not.  Represent that via a parameter pack (which might be
     * empty). In practice, for any given ItemType the extra arg is either
     * there or not, so we don't get more template explosion due to aExtraArgs.
     */
    template <typename ItemType, typename... ExtraArgTypes>
    CHIP_ERROR EncodeAttributeReportIB(const ItemType & aItem, ExtraArgTypes &&... aExtraArgs)
    {
        AttributeReportBuilder builder;
        ReturnErrorOnFailure(builder.PrepareAttribute(mAttributeReportIBsBuilder, mPath, mDataVersion));
        ReturnErrorOnFailure(builder.EncodeValue(mAttributeReportIBsBuilder, TLV::ContextTag(AttributeDataIB::Tag::kData), aItem,
                                                 std::forward<ExtraArgTypes>(aExtraArgs)...));

        return builder.FinishAttribute(mAttributeReportIBsBuilder);
    }

    /**
     * EnsureListStarted sets our mCurrentEncodingListIndex to 0, and:
     *
     * * If we are just starting the list, gets us ready to encode list items.
     *
     * * If we are continuing a chunked list, guarantees that mPath.mListOp is
     *   AppendItem after it returns.
     */
    CHIP_ERROR EnsureListStarted();

    /**
     * EnsureListEnded writes out the end of the list and our attribute data IB,
     * if we were encoding our initial list
     */
    void EnsureListEnded();

    AttributeReportIBs::Builder & mAttributeReportIBsBuilder;
    const Access::SubjectDescriptor mSubjectDescriptor;
    ConcreteDataAttributePath mPath;
    DataVersion mDataVersion;
    bool mTriedEncode      = false;
    bool mIsFabricFiltered = false;
    // mEncodingInitialList is true if we're encoding a list and we have not
    // started chunking it yet, so we're encoding a single attribute report IB
    // for the whole list, not one per item.
    bool mEncodingInitialList = false;
    // mEncodedAtLeastOneListItem becomes true once we successfully encode a list item.
    bool mEncodedAtLeastOneListItem     = false;
    ListIndex mCurrentEncodingListIndex = kInvalidListIndex;
    AttributeEncodeState mEncodeState;
};

} // namespace app
} // namespace chip
