/*
 *
 *    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 <app/AttributeReportBuilder.h>
#include <app/AttributeValueDecoder.h>
#include <app/AttributeValueEncoder.h>
#include <lib/core/CHIPError.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 {

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

protected:
    Optional<EndpointId> GetEndpointId() { return mEndpointId; }

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

} // namespace app
} // namespace chip
