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

#include <memory>
#include <type_traits>
#include <unordered_map>

#include <app/CommandSender.h>
#include <app/DeviceProxy.h>
#include <lib/support/CodeUtils.h>

#include <controller/python/chip/interaction_model/Delegate.h>
#include <controller/python/chip/native/PyChipError.h>
#include <cstdio>
#include <lib/support/logging/CHIPLogging.h>

using namespace chip;
using namespace chip::app;

using PyObject = void *;

extern "C" {
PyChipError pychip_CommandSender_SendCommand(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs,
                                             chip::EndpointId endpointId, chip::ClusterId clusterId, chip::CommandId commandId,
                                             const uint8_t * payload, size_t length, uint16_t interactionTimeoutMs,
                                             uint16_t busyWaitMs, bool suppressResponse);

PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs,
                                                   uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse,
                                                   chip::python::PyInvokeRequestData * batchCommandData, size_t length);

PyChipError pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke(
    void * appContext, DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, chip::CommandId commandId,
    const uint8_t * payload, size_t length, uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse);

PyChipError pychip_CommandSender_SendGroupCommand(chip::GroupId groupId, chip::Controller::DeviceCommissioner * devCtrl,
                                                  chip::ClusterId clusterId, chip::CommandId commandId, const uint8_t * payload,
                                                  size_t length, uint16_t busyWaitMs);
}

namespace chip {
namespace python {

using OnCommandSenderResponseCallback     = void (*)(PyObject appContext, chip::EndpointId endpointId, chip::ClusterId clusterId,
                                                 chip::CommandId commandId, size_t index,
                                                 std::underlying_type_t<Protocols::InteractionModel::Status> status,
                                                 chip::ClusterStatus clusterStatus, const uint8_t * payload, uint32_t length);
using OnCommandSenderErrorCallback        = void (*)(PyObject appContext,
                                              std::underlying_type_t<Protocols::InteractionModel::Status> status,
                                              chip::ClusterStatus clusterStatus, PyChipError chiperror);
using OnCommandSenderDoneCallback         = void (*)(PyObject appContext);
using TestOnlyOnCommandSenderDoneCallback = void (*)(PyObject appContext, python::TestOnlyPyOnDoneInfo testOnlyDoneInfo);

OnCommandSenderResponseCallback gOnCommandSenderResponseCallback         = nullptr;
OnCommandSenderErrorCallback gOnCommandSenderErrorCallback               = nullptr;
OnCommandSenderDoneCallback gOnCommandSenderDoneCallback                 = nullptr;
TestOnlyOnCommandSenderDoneCallback gTestOnlyOnCommandSenderDoneCallback = nullptr;

class CommandSenderCallback : public CommandSender::ExtendableCallback
{
public:
    CommandSenderCallback(PyObject appContext, bool isBatchedCommands, bool callTestOnlyOnDone) :
        mAppContext(appContext), mIsBatchedCommands(isBatchedCommands), mCallTestOnlyOnDone(callTestOnlyOnDone)
    {}

    void OnResponse(CommandSender * apCommandSender, const CommandSender::ResponseData & aResponseData) override
    {
        CHIP_ERROR err = CHIP_NO_ERROR;
        uint8_t buffer[CHIP_CONFIG_DEFAULT_UDP_MTU_SIZE];
        uint32_t size = 0;
        // When the apData is nullptr, means we did not receive a valid attribute data from server, status will be some error
        // status.
        if (aResponseData.data != nullptr)
        {
            // Python need to read from full TLV data the TLVReader may contain some unclean states.
            TLV::TLVWriter writer;
            writer.Init(buffer);
            err = writer.CopyContainer(TLV::AnonymousTag(), *aResponseData.data);
            if (err != CHIP_NO_ERROR)
            {
                CommandSender::ErrorData errorData = { err };
                this->OnError(apCommandSender, errorData);
                return;
            }
            size = writer.GetLengthWritten();
        }

        const app::StatusIB & statusIB = aResponseData.statusIB;

        // For legacy specific reasons when we are not processing a batch command we simply forward this to the OnError callback
        // for more information on why see https://github.com/project-chip/connectedhomeip/issues/30991.
        if (!mIsBatchedCommands && !statusIB.IsSuccess())
        {
            CommandSender::ErrorData errorData = { statusIB.ToChipError() };
            this->OnError(apCommandSender, errorData);
            return;
        }

        if (err != CHIP_NO_ERROR)
        {
            CommandSender::ErrorData errorData = { err };
            this->OnError(apCommandSender, errorData);
            return;
        }

        chip::CommandRef commandRef = aResponseData.commandRef.ValueOr(0);
        size_t index                = 0;
        err                         = GetIndexFrocommandRef(commandRef, index);
        if (err != CHIP_NO_ERROR && mIsBatchedCommands)
        {
            CommandSender::ErrorData errorData = { err };
            this->OnError(apCommandSender, errorData);
            return;
        }

        const ConcreteCommandPath & path = aResponseData.path;

        gOnCommandSenderResponseCallback(
            mAppContext, path.mEndpointId, path.mClusterId, path.mCommandId, index, to_underlying(statusIB.mStatus),
            statusIB.mClusterStatus.HasValue() ? statusIB.mClusterStatus.Value() : chip::python::kUndefinedClusterStatus, buffer,
            size);
    }

    void OnError(const CommandSender * apCommandSender, const CommandSender::ErrorData & aErrorData) override
    {
        CHIP_ERROR protocolError = aErrorData.error;
        StatusIB status(protocolError);
        gOnCommandSenderErrorCallback(mAppContext, to_underlying(status.mStatus),
                                      status.mClusterStatus.ValueOr(chip::python::kUndefinedClusterStatus),
                                      // If we have an actual IM status, pass 0
                                      // for the error code, because otherwise
                                      // the callee will think we have a stack
                                      // exception.
                                      protocolError.IsIMStatus() ? ToPyChipError(CHIP_NO_ERROR) : ToPyChipError(protocolError));
    }

    void OnDone(CommandSender * apCommandSender) override
    {
        if (mCallTestOnlyOnDone)
        {
            python::TestOnlyPyOnDoneInfo testOnlyOnDoneInfo;
            testOnlyOnDoneInfo.responseMessageCount = apCommandSender->GetInvokeResponseMessageCount();
            gTestOnlyOnCommandSenderDoneCallback(mAppContext, testOnlyOnDoneInfo);
        }
        else
        {
            gOnCommandSenderDoneCallback(mAppContext);
        }

        delete apCommandSender;
        delete this;
    };

    CHIP_ERROR GetIndexFrocommandRef(uint16_t aCommandRef, size_t & aIndex)
    {
        auto search = commandRefToIndex.find(aCommandRef);
        if (search == commandRefToIndex.end())
        {
            return CHIP_ERROR_KEY_NOT_FOUND;
        }
        aIndex = commandRefToIndex[aCommandRef];
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR AddCommandRefToIndexLookup(uint16_t aCommandRef, size_t aIndex)
    {
        auto search = commandRefToIndex.find(aCommandRef);
        if (search != commandRefToIndex.end())
        {
            return CHIP_ERROR_DUPLICATE_KEY_ID;
        }
        commandRefToIndex[aCommandRef] = aIndex;
        return CHIP_NO_ERROR;
    }

private:
    PyObject mAppContext = nullptr;
    std::unordered_map<uint16_t, size_t> commandRefToIndex;
    bool mIsBatchedCommands;
    bool mCallTestOnlyOnDone;
};

PyChipError SendBatchCommandsInternal(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs,
                                      uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse,
                                      python::TestOnlyPyBatchCommandsOverrides * testOnlyOverrides,
                                      python::PyInvokeRequestData * batchCommandData, size_t length)
{
    CommandSender::ConfigParameters config;
    CHIP_ERROR err = CHIP_NO_ERROR;

    bool testOnlySuppressTimedRequestMessage = false;
    uint16_t * testOnlyCommandRefsOverride   = nullptr;

    VerifyOrReturnError(device->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION));

    // Test only override validation checks and setup
    if (testOnlyOverrides != nullptr)
    {
        if (testOnlyOverrides->suppressTimedRequestMessage)
        {
            VerifyOrReturnError(timedRequestTimeoutMs == 0, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT));
            testOnlySuppressTimedRequestMessage = true;
        }
        if (testOnlyOverrides->overrideCommandRefsList != nullptr)
        {
            VerifyOrReturnError(length == testOnlyOverrides->overrideCommandRefsListLength,
                                ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT));
            testOnlyCommandRefsOverride = testOnlyOverrides->overrideCommandRefsList;
        }
    }

    if (testOnlyOverrides != nullptr && testOnlyOverrides->overrideRemoteMaxPathsPerInvoke)
    {
        config.SetRemoteMaxPathsPerInvoke(testOnlyOverrides->overrideRemoteMaxPathsPerInvoke);
    }
    else
    {
        auto remoteSessionParameters = device->GetSecureSession().Value()->GetRemoteSessionParameters();
        config.SetRemoteMaxPathsPerInvoke(remoteSessionParameters.GetMaxPathsPerInvoke());
    }

    bool isBatchedCommands  = true;
    bool callTestOnlyOnDone = testOnlyOverrides != nullptr;
    std::unique_ptr<CommandSenderCallback> callback =
        std::make_unique<CommandSenderCallback>(appContext, isBatchedCommands, callTestOnlyOnDone);

    bool isTimedRequest = timedRequestTimeoutMs != 0 || testOnlySuppressTimedRequestMessage;
    std::unique_ptr<CommandSender> sender =
        std::make_unique<CommandSender>(callback.get(), device->GetExchangeManager(), isTimedRequest, suppressResponse);

    SuccessOrExit(err = sender->SetCommandSenderConfig(config));

    for (size_t i = 0; i < length; i++)
    {
        chip::EndpointId endpointId = batchCommandData[i].commandPath.endpointId;
        chip::ClusterId clusterId   = batchCommandData[i].commandPath.clusterId;
        chip::CommandId commandId   = batchCommandData[i].commandPath.commandId;
        void * tlv                  = batchCommandData[i].tlvData;
        size_t tlvLength            = batchCommandData[i].tlvLength;

        const uint8_t * tlvBuffer = reinterpret_cast<const uint8_t *>(tlv);

        app::CommandPathParams cmdParams = { endpointId, /* group id */ 0, clusterId, commandId,
                                             (app::CommandPathFlags::kEndpointIdValid) };

        CommandSender::PrepareCommandParameters prepareCommandParams;
        prepareCommandParams.commandRef.SetValue(static_cast<uint16_t>(i));

        SuccessOrExit(err = sender->PrepareCommand(cmdParams, prepareCommandParams));
        {
            auto writer = sender->GetCommandDataIBTLVWriter();
            VerifyOrExit(writer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
            TLV::TLVReader reader;
            reader.Init(tlvBuffer, static_cast<uint32_t>(tlvLength));
            reader.Next();
            SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), reader));
        }

        Optional<uint16_t> timedRequestTimeout =
            timedRequestTimeoutMs != 0 ? Optional<uint16_t>(timedRequestTimeoutMs) : Optional<uint16_t>::Missing();
        CommandSender::FinishCommandParameters finishCommandParams(timedRequestTimeout);
        if (testOnlyCommandRefsOverride != nullptr)
        {
            finishCommandParams.commandRef.SetValue(testOnlyCommandRefsOverride[i]);
        }
        else
        {
            finishCommandParams.commandRef = prepareCommandParams.commandRef;
        }
        SuccessOrExit(err = sender->TestOnlyFinishCommand(finishCommandParams));

        if (testOnlyCommandRefsOverride != nullptr)
        {
            // Making sure the value we used to override CommandRef was actually used.
            VerifyOrDie(finishCommandParams.commandRef.Value() == testOnlyCommandRefsOverride[i]);
            // Ignoring the result of adding to index as the test might be trying to set duplicate CommandRefs.
            callback->AddCommandRefToIndexLookup(finishCommandParams.commandRef.Value(), i);
        }
        else
        {
            SuccessOrExit(err = callback->AddCommandRefToIndexLookup(finishCommandParams.commandRef.Value(), i));
        }
    }

    {
        Optional<System::Clock::Timeout> interactionTimeout = interactionTimeoutMs != 0
            ? MakeOptional(System::Clock::Milliseconds32(interactionTimeoutMs))
            : Optional<System::Clock::Timeout>::Missing();
        if (testOnlySuppressTimedRequestMessage)
        {
            SuccessOrExit(err = sender->TestOnlyCommandSenderTimedRequestFlagWithNoTimedInvoke(device->GetSecureSession().Value(),
                                                                                               interactionTimeout));
        }
        else
        {
            SuccessOrExit(err = sender->SendCommandRequest(device->GetSecureSession().Value(), interactionTimeout));
        }
    }

    sender.release();
    callback.release();

    // TODO(#30985): Reconsider the purpose of busyWait and if it can be broken out into it's
    // own method/primitive.
    if (busyWaitMs)
    {
        usleep(busyWaitMs * 1000);
    }

exit:
    return ToPyChipError(err);
}

} // namespace python
} // namespace chip

using namespace chip::python;

extern "C" {
void pychip_CommandSender_InitCallbacks(OnCommandSenderResponseCallback onCommandSenderResponseCallback,
                                        OnCommandSenderErrorCallback onCommandSenderErrorCallback,
                                        OnCommandSenderDoneCallback onCommandSenderDoneCallback,
                                        TestOnlyOnCommandSenderDoneCallback testOnlyOnCommandSenderDoneCallback)
{
    gOnCommandSenderResponseCallback     = onCommandSenderResponseCallback;
    gOnCommandSenderErrorCallback        = onCommandSenderErrorCallback;
    gOnCommandSenderDoneCallback         = onCommandSenderDoneCallback;
    gTestOnlyOnCommandSenderDoneCallback = testOnlyOnCommandSenderDoneCallback;
}

PyChipError pychip_CommandSender_SendCommand(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs,
                                             chip::EndpointId endpointId, chip::ClusterId clusterId, chip::CommandId commandId,
                                             const uint8_t * payload, size_t length, uint16_t interactionTimeoutMs,
                                             uint16_t busyWaitMs, bool suppressResponse)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrReturnError(device->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION));

    bool isBatchedCommands  = false;
    bool callTestOnlyOnDone = false;
    std::unique_ptr<CommandSenderCallback> callback =
        std::make_unique<CommandSenderCallback>(appContext, isBatchedCommands, callTestOnlyOnDone);
    std::unique_ptr<CommandSender> sender =
        std::make_unique<CommandSender>(callback.get(), device->GetExchangeManager(),
                                        /* is timed request */ timedRequestTimeoutMs != 0, suppressResponse);

    app::CommandPathParams cmdParams = { endpointId, /* group id */ 0, clusterId, commandId,
                                         (app::CommandPathFlags::kEndpointIdValid) };

    SuccessOrExit(err = sender->PrepareCommand(cmdParams, false));

    {
        auto writer = sender->GetCommandDataIBTLVWriter();
        TLV::TLVReader reader;
        VerifyOrExit(writer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
        reader.Init(payload, length);
        reader.Next();
        SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), reader));
    }

    SuccessOrExit(err = sender->FinishCommand(timedRequestTimeoutMs != 0 ? Optional<uint16_t>(timedRequestTimeoutMs)
                                                                         : Optional<uint16_t>::Missing()));

    SuccessOrExit(err = sender->SendCommandRequest(device->GetSecureSession().Value(),
                                                   interactionTimeoutMs != 0
                                                       ? MakeOptional(System::Clock::Milliseconds32(interactionTimeoutMs))
                                                       : Optional<System::Clock::Timeout>::Missing()));

    sender.release();
    callback.release();

    // TODO(#30985): Reconsider the purpose of busyWait and if it can be broken out into it's
    // own method/primitive.
    if (busyWaitMs)
    {
        usleep(busyWaitMs * 1000);
    }

exit:
    return ToPyChipError(err);
}

PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs,
                                                   uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse,
                                                   python::PyInvokeRequestData * batchCommandData, size_t length)
{
    python::TestOnlyPyBatchCommandsOverrides * testOnlyOverrides = nullptr;
    return SendBatchCommandsInternal(appContext, device, timedRequestTimeoutMs, interactionTimeoutMs, busyWaitMs, suppressResponse,
                                     testOnlyOverrides, batchCommandData, length);
}

PyChipError pychip_CommandSender_TestOnlySendBatchCommands(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs,
                                                           uint16_t interactionTimeoutMs, uint16_t busyWaitMs,
                                                           bool suppressResponse,
                                                           python::TestOnlyPyBatchCommandsOverrides testOnlyOverrides,
                                                           python::PyInvokeRequestData * batchCommandData, size_t length)
{
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
    return SendBatchCommandsInternal(appContext, device, timedRequestTimeoutMs, interactionTimeoutMs, busyWaitMs, suppressResponse,
                                     &testOnlyOverrides, batchCommandData, length);
#else
    return ToPyChipError(CHIP_ERROR_NOT_IMPLEMENTED);
#endif
}

PyChipError pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke(
    void * appContext, DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, chip::CommandId commandId,
    const uint8_t * payload, size_t length, uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse)
{
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST

    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrReturnError(device->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION));

    bool isBatchedCommands  = false;
    bool callTestOnlyOnDone = false;
    std::unique_ptr<CommandSenderCallback> callback =
        std::make_unique<CommandSenderCallback>(appContext, isBatchedCommands, callTestOnlyOnDone);
    std::unique_ptr<CommandSender> sender = std::make_unique<CommandSender>(callback.get(), device->GetExchangeManager(),
                                                                            /* is timed request */ true, suppressResponse);

    app::CommandPathParams cmdParams = { endpointId, /* group id */ 0, clusterId, commandId,
                                         (app::CommandPathFlags::kEndpointIdValid) };

    SuccessOrExit(err = sender->PrepareCommand(cmdParams, false));

    {
        auto writer = sender->GetCommandDataIBTLVWriter();
        TLV::TLVReader reader;
        VerifyOrExit(writer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
        reader.Init(payload, length);
        reader.Next();
        SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), reader));
    }

    SuccessOrExit(err = sender->FinishCommand(false));

    SuccessOrExit(err = sender->TestOnlyCommandSenderTimedRequestFlagWithNoTimedInvoke(
                      device->GetSecureSession().Value(),
                      interactionTimeoutMs != 0 ? MakeOptional(System::Clock::Milliseconds32(interactionTimeoutMs))
                                                : Optional<System::Clock::Timeout>::Missing()));

    sender.release();
    callback.release();

    // TODO(#30985): Reconsider the purpose of busyWait and if it can be broken out into it's
    // own method/primitive.
    if (busyWaitMs)
    {
        usleep(busyWaitMs * 1000);
    }

exit:
    return ToPyChipError(err);
#else
    return ToPyChipError(CHIP_ERROR_NOT_IMPLEMENTED);
#endif
}

PyChipError pychip_CommandSender_SendGroupCommand(chip::GroupId groupId, chip::Controller::DeviceCommissioner * devCtrl,
                                                  chip::ClusterId clusterId, chip::CommandId commandId, const uint8_t * payload,
                                                  size_t length, uint16_t busyWaitMs)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    chip::Messaging::ExchangeManager * exchangeManager = chip::app::InteractionModelEngine::GetInstance()->GetExchangeManager();
    VerifyOrReturnError(exchangeManager != nullptr, ToPyChipError(CHIP_ERROR_INCORRECT_STATE));

    std::unique_ptr<CommandSender> sender = std::make_unique<CommandSender>(nullptr /* callback */, exchangeManager);

    app::CommandPathParams cmdParams = { groupId, clusterId, commandId, (app::CommandPathFlags::kGroupIdValid) };

    SuccessOrExit(err = sender->PrepareCommand(cmdParams, false));

    {
        auto writer = sender->GetCommandDataIBTLVWriter();
        TLV::TLVReader reader;
        VerifyOrExit(writer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
        reader.Init(payload, length);
        reader.Next();
        SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), reader));
    }

    SuccessOrExit(err = sender->FinishCommand(Optional<uint16_t>::Missing()));

    {
        auto fabricIndex = devCtrl->GetFabricIndex();

        chip::Transport::OutgoingGroupSession session(groupId, fabricIndex);
        SuccessOrExit(err = sender->SendGroupCommandRequest(chip::SessionHandle(session)));
    }

    // TODO(#30985): Reconsider the purpose of busyWait and if it can be broken out into it's
    // own method/primitive.
    if (busyWaitMs)
    {
        usleep(busyWaitMs * 1000);
    }

exit:
    return ToPyChipError(err);
}
}
