/*
 *
 *    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.
 */

/**
 *    @file
 *      This file provides implementation of ExchangeMessageDispatch class.
 */

#include <errno.h>
#include <inttypes.h>
#include <memory>

#include <lib/support/CodeUtils.h>
#include <messaging/ExchangeMessageDispatch.h>
#include <messaging/ReliableMessageContext.h>
#include <messaging/ReliableMessageMgr.h>
#include <protocols/secure_channel/Constants.h>

namespace chip {
namespace Messaging {

CHIP_ERROR ExchangeMessageDispatch::SendMessage(SessionManager * sessionManager, const SessionHandle & session, uint16_t exchangeId,
                                                bool isInitiator, ReliableMessageContext * reliableMessageContext,
                                                bool isReliableTransmission, Protocols::Id protocol, uint8_t type,
                                                System::PacketBufferHandle && message)
{
    ReturnErrorCodeIf(!MessagePermitted(protocol, type), CHIP_ERROR_INVALID_ARGUMENT);

    PayloadHeader payloadHeader;
    payloadHeader.SetExchangeID(exchangeId).SetMessageType(protocol, type).SetInitiator(isInitiator);

    if (session->AllowsMRP())
    {
        // If there is a pending acknowledgment piggyback it on this message.
        if (reliableMessageContext->HasPiggybackAckPending())
        {
            payloadHeader.SetAckMessageCounter(reliableMessageContext->TakePendingPeerAckMessageCounter());
        }

        if (IsReliableTransmissionAllowed() && reliableMessageContext->AutoRequestAck() &&
            reliableMessageContext->GetReliableMessageMgr() != nullptr && isReliableTransmission)
        {
            auto * reliableMessageMgr = reliableMessageContext->GetReliableMessageMgr();

            payloadHeader.SetNeedsAck(true);

            ReliableMessageMgr::RetransTableEntry * entry = nullptr;

            // Add to Table for subsequent sending
            ReturnErrorOnFailure(reliableMessageMgr->AddToRetransTable(reliableMessageContext, &entry));
            auto deleter = [reliableMessageMgr](ReliableMessageMgr::RetransTableEntry * e) {
                reliableMessageMgr->ClearRetransTable(*e);
            };
            std::unique_ptr<ReliableMessageMgr::RetransTableEntry, decltype(deleter)> entryOwner(entry, deleter);

            ReturnErrorOnFailure(
                sessionManager->PrepareMessage(session, payloadHeader, std::move(message), entryOwner->retainedBuf));
            CHIP_ERROR err = sessionManager->SendPreparedMessage(session, entryOwner->retainedBuf);
            err            = ReliableMessageMgr::MapSendError(err, exchangeId, isInitiator);
            ReturnErrorOnFailure(err);
            reliableMessageMgr->StartRetransmision(entryOwner.release());
        }
        else
        {
            ReturnErrorOnFailure(PrepareAndSendNonMRPMessage(sessionManager, session, payloadHeader, std::move(message)));
        }
    }
    else
    {
        ReturnErrorOnFailure(PrepareAndSendNonMRPMessage(sessionManager, session, payloadHeader, std::move(message)));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExchangeMessageDispatch::PrepareAndSendNonMRPMessage(SessionManager * sessionManager, const SessionHandle & session,
                                                                PayloadHeader & payloadHeader,
                                                                System::PacketBufferHandle && message)
{
    payloadHeader.SetNeedsAck(false);
    EncryptedPacketBufferHandle preparedMessage;
    ReturnErrorOnFailure(sessionManager->PrepareMessage(session, payloadHeader, std::move(message), preparedMessage));
    ReturnErrorOnFailure(sessionManager->SendPreparedMessage(session, preparedMessage));

    return CHIP_NO_ERROR;
}

} // namespace Messaging
} // namespace chip
