/*
 * Copyright (c) Contributors to the Open 3D Engine Project.
 * For complete copyright and license terms please see the LICENSE at the root of this distribution.
 *
 * SPDX-License-Identifier: Apache-2.0 OR MIT
 *
 */

#pragma once

#include <AzNetworking/DataStructures/FixedSizeBitset.h>
#include <AzNetworking/DataStructures/TimeoutQueue.h>
#include <AzNetworking/ConnectionLayer/IConnection.h>
#include <AzNetworking/ConnectionLayer/SequenceGenerator.h>
#include <AzNetworking/UdpTransport/UdpPacketHeader.h>
#include <AzNetworking/UdpTransport/UdpPacketIdWindow.h>

namespace AzNetworking
{
    //! @class UdpPacketTracker
    //! @brief packet tracking mechanism for sending, acking, and detecting dropped packets.
    class UdpPacketTracker
    {
    public:

        UdpPacketTracker();
        ~UdpPacketTracker();

        //! Resets all internal state for this packet tracker.
        void Reset();

        //! Returns the next packet id for this UdpPacketTracker instance.
        //! @return the next sequence id for this UdpPacketTracker instance
        PacketId GetNextPacketId();

        //! Process a received packet header.
        //! @param connection the connection this packet was received on, used for ack callbacks
        //! @param header     the packet header received to process
        //! @return boolean true on successful handling of the received header
        bool ProcessReceived(UdpConnection* connection, UdpPacketHeader& header);

        //! Returns whether or not a particular packet was confirmed received by the remote connection.
        //! @param sequenceId the sequence number of the packet to check the ack status of
        //! @return boolean true if the requested sequence id was acked, false otherwise
        PacketAckState GetPacketAckStatus(PacketId packetId) const;

        //! Returns the last received remote sequence id.
        //! @return the last received remote sequence id
        SequenceId GetLastReceivedSequenceId() const;

        //! Returns a bit sequence representing the last received packets from the remote connection.
        //! @param outWindow window to store the output bit sequence in
        //! @return reference to the output parameter
        BitsetChunk& GetSequencedAckHistory(BitsetChunk& outWindow) const;

        //! Const access to the packet trackers received window.
        //! @return const reference to the packet trackers received window
        const UdpPacketIdWindow& GetReceivedWindow() const;

        //! Const access to the packet trackers acknowledged window.
        //! @return const reference to the packet trackers acknowledged window
        const UdpPacketIdWindow& GetAcknowledgedWindow() const;

    private:

        PacketId          m_nextPacketId;
        UdpPacketIdWindow m_receivedWindow;     //< Packets received that were generated by the remote endpoint
        UdpPacketIdWindow m_acknowledgedWindow; //< Packets we sent that have been acked by the remote endpoint
    };
}

#include <AzNetworking/UdpTransport/UdpPacketTracker.inl>
