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

package report

import (
	
	
	

	
	
)

const (
	// packetsPerHistoryEntry represents how many packets are in the bitmask for
	// each entry in the `packets` slice in the receiver stream. Because we use
	// a uint64, we can keep track of 64 packets per entry.
	packetsPerHistoryEntry = 64
)

type receiverStream struct {
	ssrc         uint32
	receiverSSRC uint32
	clockRate    float64

	m                    sync.Mutex
	size                 uint16
	packets              []uint64
	started              bool
	seqnumCycles         uint16
	lastSeqnum           uint16
	lastReportSeqnum     uint16
	lastRTPTimeRTP       uint32
	lastRTPTimeTime      time.Time
	jitter               float64
	lastSenderReport     uint32
	lastSenderReportTime time.Time
	totalLost            uint32
}

func newReceiverStream( uint32,  uint32) *receiverStream {
	 := rand.Uint32() // #nosec

	return &receiverStream{
		ssrc:         ,
		receiverSSRC: ,
		clockRate:    float64(),
		size:         128,
		packets:      make([]uint64, 128),
	}
}

func ( *receiverStream) ( time.Time,  *rtp.Header) {
	.m.Lock()
	defer .m.Unlock()

	//nolint:nestif
	if !.started { // first frame
		.started = true
		.setReceived(.SequenceNumber)
		.lastSeqnum = .SequenceNumber
		.lastReportSeqnum = .SequenceNumber - 1
		.lastRTPTimeRTP = .Timestamp
		.lastRTPTimeTime = 
	} else { // following frames
		.setReceived(.SequenceNumber)

		 := .SequenceNumber - .lastSeqnum
		if  > 0 &&  < (1<<15) {
			// wrap around
			if .SequenceNumber < .lastSeqnum {
				.seqnumCycles++
			}

			// set missing packets as missing
			for  := .lastSeqnum + 1;  != .SequenceNumber; ++ {
				.delReceived()
			}

			.lastSeqnum = .SequenceNumber
		}

		// compute jitter
		// https://tools.ietf.org/html/rfc3550#page-39
		 := .Sub(.lastRTPTimeTime).Seconds()*.clockRate -
			(float64(.Timestamp) - float64(.lastRTPTimeRTP))
		if  < 0 {
			 = -
		}
		.jitter += ( - .jitter) / 16
		.lastRTPTimeRTP = .Timestamp
		.lastRTPTimeTime = 
	}
}

func ( *receiverStream) ( uint16) {
	 :=  % (.size * packetsPerHistoryEntry)
	.packets[/packetsPerHistoryEntry] |= 1 << ( % packetsPerHistoryEntry)
}

func ( *receiverStream) ( uint16) {
	 :=  % (.size * packetsPerHistoryEntry)
	.packets[/packetsPerHistoryEntry] &^= 1 << ( % packetsPerHistoryEntry)
}

func ( *receiverStream) ( uint16) bool {
	 :=  % (.size * packetsPerHistoryEntry)

	return (.packets[/packetsPerHistoryEntry] & (1 << ( % packetsPerHistoryEntry))) != 0
}

func ( *receiverStream) ( time.Time,  *rtcp.SenderReport) {
	.m.Lock()
	defer .m.Unlock()

	.lastSenderReport = uint32(.NTPTime >> 16) //nolint:gosec // G115
	.lastSenderReportTime = 
}

func ( *receiverStream) ( time.Time) *rtcp.ReceiverReport {
	.m.Lock()
	defer .m.Unlock()

	 := .lastSeqnum - .lastReportSeqnum
	 := func() uint32 {
		if .lastSeqnum == .lastReportSeqnum {
			return 0
		}

		 := uint32(0)
		for  := .lastReportSeqnum + 1;  != .lastSeqnum; ++ {
			if !.getReceived() {
				++
			}
		}

		return 
	}()
	.totalLost += 

	// allow up to 24 bits
	if  > 0xFFFFFF {
		 = 0xFFFFFF
	}
	if .totalLost > 0xFFFFFF {
		.totalLost = 0xFFFFFF
	}

	 := &rtcp.ReceiverReport{
		SSRC: .receiverSSRC,
		Reports: []rtcp.ReceptionReport{
			{
				SSRC:               .ssrc,
				LastSequenceNumber: uint32(.seqnumCycles)<<16 | uint32(.lastSeqnum),
				LastSenderReport:   .lastSenderReport,
				FractionLost:       uint8(float64(*256) / float64()),
				TotalLost:          .totalLost,
				Delay: func() uint32 {
					if .lastSenderReportTime.IsZero() {
						return 0
					}

					return uint32(.Sub(.lastSenderReportTime).Seconds() * 65536)
				}(),
				Jitter: uint32(.jitter),
			},
		},
	}

	.lastReportSeqnum = .lastSeqnum

	return 
}