// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package rtcp

import 

// A ReceptionReport block conveys statistics on the reception of RTP packets
// from a single synchronization source.
type ReceptionReport struct {
	// The SSRC identifier of the source to which the information in this
	// reception report block pertains.
	SSRC uint32
	// The fraction of RTP data packets from source SSRC lost since the
	// previous SR or RR packet was sent, expressed as a fixed point
	// number with the binary point at the left edge of the field.
	FractionLost uint8
	// The total number of RTP data packets from source SSRC that have
	// been lost since the beginning of reception.
	TotalLost uint32
	// The low 16 bits contain the highest sequence number received in an
	// RTP data packet from source SSRC, and the most significant 16
	// bits extend that sequence number with the corresponding count of
	// sequence number cycles.
	LastSequenceNumber uint32
	// An estimate of the statistical variance of the RTP data packet
	// interarrival time, measured in timestamp units and expressed as an
	// unsigned integer.
	Jitter uint32
	// The middle 32 bits out of 64 in the NTP timestamp received as part of
	// the most recent RTCP sender report (SR) packet from source SSRC. If no
	// SR has been received yet, the field is set to zero.
	LastSenderReport uint32
	// The delay, expressed in units of 1/65536 seconds, between receiving the
	// last SR packet from source SSRC and sending this reception report block.
	// If no SR packet has been received yet from SSRC, the field is set to zero.
	Delay uint32
}

const (
	receptionReportLength = 24
	fractionLostOffset    = 4
	totalLostOffset       = 5
	lastSeqOffset         = 8
	jitterOffset          = 12
	lastSROffset          = 16
	delayOffset           = 20
)

// Marshal encodes the ReceptionReport in binary
func ( ReceptionReport) () ([]byte, error) {
	/*
	 *  0                   1                   2                   3
	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
	 * |                              SSRC                             |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * | fraction lost |       cumulative number of packets lost       |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |           extended highest sequence number received           |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |                      interarrival jitter                      |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |                         last SR (LSR)                         |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |                   delay since last SR (DLSR)                  |
	 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
	 */

	 := make([]byte, receptionReportLength)

	binary.BigEndian.PutUint32(, .SSRC)

	[fractionLostOffset] = .FractionLost

	// pack TotalLost into 24 bits
	if .TotalLost >= (1 << 25) {
		return nil, errInvalidTotalLost
	}
	 := [totalLostOffset:]
	[0] = byte(.TotalLost >> 16)
	[1] = byte(.TotalLost >> 8)
	[2] = byte(.TotalLost)

	binary.BigEndian.PutUint32([lastSeqOffset:], .LastSequenceNumber)
	binary.BigEndian.PutUint32([jitterOffset:], .Jitter)
	binary.BigEndian.PutUint32([lastSROffset:], .LastSenderReport)
	binary.BigEndian.PutUint32([delayOffset:], .Delay)

	return , nil
}

// Unmarshal decodes the ReceptionReport from binary
func ( *ReceptionReport) ( []byte) error {
	if len() < receptionReportLength {
		return errPacketTooShort
	}

	/*
	 *  0                   1                   2                   3
	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
	 * |                              SSRC                             |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * | fraction lost |       cumulative number of packets lost       |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |           extended highest sequence number received           |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |                      interarrival jitter                      |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |                         last SR (LSR)                         |
	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 * |                   delay since last SR (DLSR)                  |
	 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
	 */

	.SSRC = binary.BigEndian.Uint32()
	.FractionLost = [fractionLostOffset]

	 := [totalLostOffset:]
	.TotalLost = uint32([2]) | uint32([1])<<8 | uint32([0])<<16

	.LastSequenceNumber = binary.BigEndian.Uint32([lastSeqOffset:])
	.Jitter = binary.BigEndian.Uint32([jitterOffset:])
	.LastSenderReport = binary.BigEndian.Uint32([lastSROffset:])
	.Delay = binary.BigEndian.Uint32([delayOffset:])

	return nil
}

func ( *ReceptionReport) () int {
	return receptionReportLength
}