/*
 *
 *    Copyright (c) 2021 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/CommandHandler.h>
#include <app/ConcreteClusterPath.h>
#include <app/ConcreteCommandPath.h>
#include <app/data-model/Decode.h>
#include <app/data-model/FabricScoped.h>
#include <app/data-model/List.h> // So we can encode lists
#include <lib/core/DataModelTypes.h>
#include <lib/support/Iterators.h>

#include <type_traits>
namespace chip {
namespace app {

/*
 * This interface permits applications to register a server-side command handler
 * at run-time for a given cluster. The handler can either be configured to handle all endpoints
 * for the given cluster or only handle a specific endpoint.
 *
 * If a command is not handled through this interface, it will default to invoking the generated DispatchSingleClusterCommand
 * instead.
 *
 */
class CommandHandlerInterface
{
public:
    struct HandlerContext
    {
    public:
        HandlerContext(CommandHandler & commandHandler, const ConcreteCommandPath & requestPath, TLV::TLVReader & aReader) :
            mCommandHandler(commandHandler), mRequestPath(requestPath), mPayload(aReader)
        {}

        void SetCommandHandled() { mCommandHandled = true; }
        void SetCommandNotHandled() { mCommandHandled = false; }

        /*
         * Returns a TLVReader positioned at the TLV struct that contains the payload of the command.
         *
         * If the reader is requested from the context, then we can assume there is an intention
         * to access the payload of this command and consequently, to handle this command.
         *
         * If this is not true, the application should call SetCommandNotHandled().
         *
         */
        TLV::TLVReader & GetReader()
        {
            SetCommandHandled();
            return mPayload;
        }

        CommandHandler & mCommandHandler;
        const ConcreteCommandPath & mRequestPath;
        TLV::TLVReader & mPayload;
        bool mCommandHandled = false;
    };

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

    virtual ~CommandHandlerInterface() {}

    /**
     * Callback that must be implemented to handle an invoke request.
     *
     * The callee is required to handle *all* errors that may occur during the handling of this command,
     * including errors like those encountered during decode and encode of the payloads as
     * well as application-specific errors. As part of handling the error, the callee is required
     * to handle generation of an appropriate status response.
     *
     * The only exception to this rule is if the HandleCommand helper method is used below - it will
     * help handle some of these cases (see below).
     *
     * @param [in] handlerContext Context that encapsulates the current invoke request.
     *                            Handlers are responsible for correctly calling SetCommandHandled()
     *                            on the context if they did handle the command.
     *
     *                            This is not necessary if the HandleCommand() method below is invoked.
     */
    virtual void InvokeCommand(HandlerContext & handlerContext) = 0;

    typedef Loop (*CommandIdCallback)(CommandId id, void * context);

    /**
     * Function that may be implemented to enumerate accepted (client-to-server)
     * commands for the given cluster.
     *
     * If this function returns CHIP_ERROR_NOT_IMPLEMENTED, the list of accepted
     * commands will come from the endpoint metadata for the cluster.
     *
     * If this function returns any other error, that will be treated as an
     * error condition by the caller, and handling will depend on the caller.
     *
     * Otherwise the list of accepted commands will be the list of values passed
     * to the provided callback.
     *
     * The implementation _must_ pass the provided context to the callback.
     *
     * If the callback returns Loop::Break, there must be no more calls to it.
     * This is used by callbacks that just look for a particular value in the
     * list.
     */
    virtual CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
    {
        return CHIP_ERROR_NOT_IMPLEMENTED;
    }

    /**
     * Function that may be implemented to enumerate generated (response)
     * commands for the given cluster.
     *
     * If this function returns CHIP_ERROR_NOT_IMPLEMENTED, the list of
     * generated commands will come from the endpoint metadata for the cluster.
     *
     * If this function returns any other error, that will be treated as an
     * error condition by the caller, and handling will depend on the caller.
     *
     * Otherwise the list of generated commands will be the list of values
     * passed to the provided callback.
     *
     * The implementation _must_ pass the provided context to the callback.
     *
     * If the callback returns Loop::Break, there must be no more calls to it.
     * This is used by callbacks that just look for a particular value in the
     * list.
     */
    virtual CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
    {
        return CHIP_ERROR_NOT_IMPLEMENTED;
    }

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

    /**
     * Check whether a this CommandHandlerInterface is relevant for a
     * particular endpoint+cluster.  An CommandHandlerInterface will be used
     * for an invoke 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 CommandHandlerInterface 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 CommandHandlerInterface wants to handle the same set of
     * commands as we do.
     */
    bool Matches(const CommandHandlerInterface & aOther) const
    {
        return mClusterId == aOther.mClusterId &&
            (!mEndpointId.HasValue() || !aOther.mEndpointId.HasValue() || mEndpointId.Value() == aOther.mEndpointId.Value());
    }

protected:
    /*
     * Helper function to automatically de-serialize the data payload into a cluster object
     * of type RequestT if the Cluster ID and Command ID in the context match. Upon successful
     * de-serialization, the provided function is invoked and passed in a reference to the cluster object.
     *
     * Any errors encountered in this function prior to calling func result in the automatic generation of a status response.
     * If `func` is called, the responsibility for doing so shifts to the callee to handle any further errors that are encountered.
     *
     * The provided function is expected to have the following signature:
     *  void Func(HandlerContext &handlerContext, const RequestT &requestPayload);
     */
    template <typename RequestT, typename FuncT,
              typename std::enable_if_t<!DataModel::IsFabricScoped<RequestT>::value, bool> = true>
    void HandleCommand(HandlerContext & handlerContext, FuncT func)
    {
        if (!handlerContext.mCommandHandled && (handlerContext.mRequestPath.mClusterId == RequestT::GetClusterId()) &&
            (handlerContext.mRequestPath.mCommandId == RequestT::GetCommandId()))
        {
            RequestT requestPayload;

            //
            // If the command matches what the caller is looking for, let's mark this as being handled
            // even if errors happen after this. This ensures that we don't execute any fall-back strategies
            // to handle this command since at this point, the caller is taking responsibility for handling
            // the command in its entirety, warts and all.
            //
            handlerContext.SetCommandHandled();

            if (DataModel::Decode(handlerContext.mPayload, requestPayload) != CHIP_NO_ERROR)
            {
                handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath,
                                                         Protocols::InteractionModel::Status::InvalidCommand);
                return;
            }

            func(handlerContext, requestPayload);
        }
    }

    /*
     * Helper function to automatically de-serialize the data payload into a cluster object
     * of type RequestT if the Cluster ID and Command ID in the context match. Upon successful
     * de-serialization, the provided function is invoked and passed in a reference to the cluster object.
     *
     * Any errors encountered in this function prior to calling func result in the automatic generation of a status response.
     * If `func` is called, the responsibility for doing so shifts to the callee to handle any further errors that are encountered.
     *
     * The provided function is expected to have the following signature:
     *  void Func(HandlerContext &handlerContext, const RequestT &requestPayload);
     */
    template <typename RequestT, typename FuncT, typename std::enable_if_t<DataModel::IsFabricScoped<RequestT>::value, bool> = true>
    void HandleCommand(HandlerContext & handlerContext, FuncT func)
    {
        if (!handlerContext.mCommandHandled && (handlerContext.mRequestPath.mClusterId == RequestT::GetClusterId()) &&
            (handlerContext.mRequestPath.mCommandId == RequestT::GetCommandId()))
        {
            RequestT requestPayload;

            //
            // If the command matches what the caller is looking for, let's mark this as being handled
            // even if errors happen after this. This ensures that we don't execute any fall-back strategies
            // to handle this command since at this point, the caller is taking responsibility for handling
            // the command in its entirety, warts and all.
            //
            handlerContext.SetCommandHandled();

            if (requestPayload.Decode(handlerContext.mPayload, handlerContext.mCommandHandler.GetAccessingFabricIndex()) !=
                CHIP_NO_ERROR)
            {
                handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath,
                                                         Protocols::InteractionModel::Status::InvalidCommand);
                return;
            }

            func(handlerContext, requestPayload);
        }
    }

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

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

} // namespace app
} // namespace chip
