/*
 *
 *    Copyright (c) 2023 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 "core/BaseCluster.h"
#include "core/Endpoint.h"

#include "lib/support/logging/CHIPLogging.h"

namespace matter {
namespace casting {
namespace core {
template <typename ResponseType>
using CommandSuccessCallbackType = std::function<void(void * context, const ResponseType & responseObject)>;
using CommandFailureCallbackType = std::function<void(void * context, CHIP_ERROR err)>;

template <typename RequestType>
struct CommandContext;

template <typename RequestType>
class Command
{
public:
    Command(memory::Weak<core::Endpoint> endpoint) { this->mEndpoint = endpoint; }

    /**
     * @brief Invokes this command on the associated Endpoint and corresponding Cluster
     *
     * @param request request data corresponding to this command invocation
     * @param successCb Called on command execution success, with responseData
     * @param failureCb Called on command execution failure
     * @param timedInvokeTimeoutMs command timeout
     */
    void Invoke(RequestType request, void * context, CommandSuccessCallbackType<typename RequestType::ResponseType> successCb,
                CommandFailureCallbackType failureCb, const chip::Optional<uint16_t> & timedInvokeTimeoutMs)
    {
        memory::Strong<core::Endpoint> endpoint = this->GetEndpoint().lock();
        if (endpoint)
        {
            CommandContext<RequestType> * commandContext =
                new CommandContext<RequestType>(endpoint, request, context, successCb, failureCb, timedInvokeTimeoutMs);

            endpoint->GetCastingPlayer()->FindOrEstablishSession(
                commandContext,
                // FindOrEstablishSession success handler
                [](void * _context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
                    CommandContext<RequestType> * _commandContext = static_cast<CommandContext<RequestType> *>(_context);
                    ChipLogProgress(AppServer, "<Command>::Invoke() Found or established session");

                    // Invoke command
                    MediaClusterBase cluster(exchangeMgr, sessionHandle, _commandContext->mEndpoint->GetId());
                    CHIP_ERROR err = cluster.template InvokeCommand(
                        _commandContext->mRequest, _commandContext,
                        // Command success handler
                        [](void * __context, const typename RequestType::ResponseType & response) {
                            CommandContext<RequestType> * __commandContext = static_cast<CommandContext<RequestType> *>(__context);
                            ChipLogProgress(AppServer, "<Command>::Invoke() response success");
                            __commandContext->mSuccessCb(__commandContext->mClientContext, response);
                            delete __commandContext;
                        },
                        // Command failure handler
                        [](void * __context, CHIP_ERROR error) {
                            CommandContext<RequestType> * __commandContext = static_cast<CommandContext<RequestType> *>(__context);
                            ChipLogError(AppServer,
                                         "<Command>::Invoke() failure response on EndpointId: %d with error: "
                                         "%" CHIP_ERROR_FORMAT,
                                         __commandContext->mEndpoint->GetId(), error.Format());
                            __commandContext->mFailureCb(__commandContext->mClientContext, error);
                            delete __commandContext;
                        },
                        _commandContext->mTimedInvokeTimeoutMs);

                    // error in invoking the command
                    if (err != CHIP_NO_ERROR)
                    {
                        ChipLogError(AppServer,
                                     "<Command>::Invoke() failure in invoking command on EndpointId: %d with error: "
                                     "%" CHIP_ERROR_FORMAT,
                                     _commandContext->mEndpoint->GetId(), err.Format());
                        _commandContext->mFailureCb(_commandContext->mClientContext, err);
                        delete _commandContext;
                    }
                },
                // FindOrEstablishSession failure handler
                [](void * _context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
                    CommandContext<RequestType> * _commandContext = static_cast<CommandContext<RequestType> *>(_context);
                    ChipLogError(AppServer,
                                 "<Command>::Invoke() failure in retrieving session info for peerId.nodeId: "
                                 "0x" ChipLogFormatX64 ", peer.fabricIndex: %d with error: %" CHIP_ERROR_FORMAT,
                                 ChipLogValueX64(peerId.GetNodeId()), peerId.GetFabricIndex(), error.Format());
                    _commandContext->mFailureCb(_commandContext->mClientContext, error);
                    delete _commandContext;
                });
        }
        else
        {
            ChipLogError(AppServer, "<Command>::Invoke() failure in retrieving Endpoint");
            failureCb(context, CHIP_ERROR_INCORRECT_STATE);
        }
    }

protected:
    memory::Weak<core::Endpoint> GetEndpoint() const { return mEndpoint.lock(); }
    memory::Weak<core::Endpoint> mEndpoint;
};

/**
 * @brief Context object used by the Command class during the Invoke API's execution
 */
template <typename RequestType>
struct CommandContext
{
    CommandContext(memory::Strong<core::Endpoint> endpoint, RequestType request, void * context,
                   CommandSuccessCallbackType<typename RequestType::ResponseType> successCb, CommandFailureCallbackType failureCb,
                   const chip::Optional<uint16_t> & timedInvokeTimeoutMs) :
        mSuccessCb(successCb),
        mFailureCb(failureCb)
    {
        mEndpoint             = endpoint;
        mRequest              = request;
        mClientContext        = context;
        mTimedInvokeTimeoutMs = timedInvokeTimeoutMs;
    }

    memory::Strong<core::Endpoint> mEndpoint;
    RequestType mRequest;
    void * mClientContext;
    CommandSuccessCallbackType<typename RequestType::ResponseType> mSuccessCb;
    CommandFailureCallbackType mFailureCb;
    chip::Optional<uint16_t> mTimedInvokeTimeoutMs;
};

}; // namespace core
}; // namespace casting
}; // namespace matter
