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

package rfc8888

import (
	

	
	
)

const maxReportsPerReportBlock = 16384

type streamLog struct {
	ssrc                       uint32
	sequence                   sequencenumber.Unwrapper
	init                       bool
	nextSequenceNumberToReport int64 // next to report
	lastSequenceNumberReceived int64 // highest received
	log                        map[int64]*packetReport
}

func newStreamLog( uint32) *streamLog {
	return &streamLog{
		ssrc:                       ,
		sequence:                   sequencenumber.Unwrapper{},
		init:                       false,
		nextSequenceNumberToReport: 0,
		lastSequenceNumberReceived: 0,
		log:                        map[int64]*packetReport{},
	}
}

func ( *streamLog) ( time.Time,  uint16,  uint8) {
	 := .sequence.Unwrap()
	if !.init {
		.init = true
		.nextSequenceNumberToReport = 
	}
	.log[] = &packetReport{
		arrivalTime: ,
		ecn:         ,
	}
	if .lastSequenceNumberReceived <  {
		.lastSequenceNumberReceived = 
	}
}

// metricsAfter iterates over all packets order of their sequence number.
// Packets are removed until the first loss is detected.
func ( *streamLog) ( time.Time,  int64) rtcp.CCFeedbackReportBlock {
	if len(.log) == 0 {
		return rtcp.CCFeedbackReportBlock{
			MediaSSRC:     .ssrc,
			BeginSequence: uint16(.nextSequenceNumberToReport), //nolint:gosec // G115
			MetricBlocks:  []rtcp.CCFeedbackMetricBlock{},
		}
	}
	 := .lastSequenceNumberReceived - .nextSequenceNumberToReport + 1
	if  >  {
		 = 
		.nextSequenceNumberToReport = .lastSequenceNumberReceived -  + 1
	}
	 := make([]rtcp.CCFeedbackMetricBlock, )
	 := .nextSequenceNumberToReport
	 := .nextSequenceNumberToReport
	 := false
	for  := ;  <= .lastSequenceNumberReceived; ++ { //nolint:varnamelen // i int64
		 := false
		 := uint8(0)
		 := uint16(0)
		if ,  := .log[];  {
			 = true
			 = .ecn
			 = getArrivalTimeOffset(, .arrivalTime)
		}
		[-] = rtcp.CCFeedbackMetricBlock{
			Received:          ,
			ECN:               rtcp.ECN(),
			ArrivalTimeOffset: ,
		}

		if ! {
			if  &&  == .nextSequenceNumberToReport {
				delete(.log, )
				.nextSequenceNumberToReport++
				 = 
			}
			if  > +1 {
				 = true
			}
		}
	}

	return rtcp.CCFeedbackReportBlock{
		MediaSSRC:     .ssrc,
		BeginSequence: uint16(), //nolint:gosec // G115
		MetricBlocks:  ,
	}
}

func getArrivalTimeOffset( time.Time,  time.Time) uint16 {
	if .Before() {
		return 0x1FFF
	}
	 := uint16(.Sub().Seconds() * 1024.0)
	if  > 0x1FFD {
		return 0x1FFE
	}

	return 
}