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

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#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
