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

package rtcp

import (
	
	
	
	
)

// ReceiverEstimatedMaximumBitrate contains the receiver's estimated maximum bitrate.
// see: https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
type ReceiverEstimatedMaximumBitrate struct {
	// SSRC of sender
	SenderSSRC uint32

	// Estimated maximum bitrate
	Bitrate float32

	// SSRC entries which this packet applies to
	SSRCs []uint32
}

// Marshal serializes the packet and returns a byte slice.
func ( ReceiverEstimatedMaximumBitrate) () ( []byte,  error) {
	// Allocate a buffer of the exact output size.
	 = make([]byte, .MarshalSize())

	// Write to our buffer.
	,  := .MarshalTo()
	if  != nil {
		return nil, 
	}

	// This will always be true but just to be safe.
	if  != len() {
		return nil, errWrongMarshalSize
	}

	return , nil
}

// MarshalSize returns the size of the packet once marshaled
func ( ReceiverEstimatedMaximumBitrate) () int {
	return 20 + 4*len(.SSRCs)
}

// MarshalTo serializes the packet to the given byte slice.
func ( ReceiverEstimatedMaximumBitrate) ( []byte) ( int,  error) {
	const  = 0x3FFFFp+63
	/*
	    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
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |V=2|P| FMT=15  |   PT=206      |             length            |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                  SSRC of packet sender                        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                  SSRC of media source                         |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  Unique identifier 'R' 'E' 'M' 'B'                            |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |   SSRC feedback                                               |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  ...                                                          |
	*/

	 := .MarshalSize()
	if len() <  {
		return 0, errPacketTooShort
	}

	[0] = 143 // v=2, p=0, fmt=15
	[1] = 206

	// Length of this packet in 32-bit words minus one.
	 := uint16((.MarshalSize() / 4) - 1)
	binary.BigEndian.PutUint16([2:4], )

	binary.BigEndian.PutUint32([4:8], .SenderSSRC)
	binary.BigEndian.PutUint32([8:12], 0) // always zero

	// ALL HAIL REMB
	[12] = 'R'
	[13] = 'E'
	[14] = 'M'
	[15] = 'B'

	// Write the length of the ssrcs to follow at the end
	[16] = byte(len(.SSRCs))

	 := 0
	 := .Bitrate

	if  >=  {
		 = 
	}

	if  < 0 {
		return 0, errInvalidBitrate
	}

	for  >= (1 << 18) {
		 /= 2.0
		++
	}

	if  >= (1 << 6) {
		return 0, errInvalidBitrate
	}

	 := uint(math.Floor(float64()))

	// We can't quite use the binary package because
	// a) it's a uint24 and b) the exponent is only 6-bits
	// Just trust me; this is big-endian encoding.
	[17] = byte(<<2) | byte(>>16)
	[18] = byte( >> 8)
	[19] = byte()

	// Write the SSRCs at the very end.
	 = 20
	for ,  := range .SSRCs {
		binary.BigEndian.PutUint32([:+4], )
		 += 4
	}

	return , nil
}

// Unmarshal reads a REMB packet from the given byte slice.
func ( *ReceiverEstimatedMaximumBitrate) ( []byte) ( error) {
	const  = 0x7FFFFF
	/*
	    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
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |V=2|P| FMT=15  |   PT=206      |             length            |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                  SSRC of packet sender                        |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                  SSRC of media source                         |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  Unique identifier 'R' 'E' 'M' 'B'                            |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |   SSRC feedback                                               |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |  ...                                                          |
	*/

	// 20 bytes is the size of the packet with no SSRCs
	if len() < 20 {
		return errPacketTooShort
	}

	// version  must be 2
	 := [0] >> 6
	if  != 2 {
		return fmt.Errorf("%w expected(2) actual(%d)", errBadVersion, )
	}

	// padding must be unset
	 := ([0] >> 5) & 1
	if  != 0 {
		return fmt.Errorf("%w expected(0) actual(%d)", errWrongPadding, )
	}

	// fmt must be 15
	 := [0] & 31
	if  != 15 {
		return fmt.Errorf("%w expected(15) actual(%d)", errWrongFeedbackType, )
	}

	// Must be payload specific feedback
	if [1] != 206 {
		return fmt.Errorf("%w expected(206) actual(%d)", errWrongPayloadType, [1])
	}

	// length is the number of 32-bit words, minus 1
	 := binary.BigEndian.Uint16([2:4])
	 := int(( + 1) * 4)

	// There's not way this could be legit
	if  < 20 {
		return errHeaderTooSmall
	}

	// Make sure the buffer is large enough.
	if len() <  {
		return errPacketTooShort
	}

	// The sender SSRC is 32-bits
	.SenderSSRC = binary.BigEndian.Uint32([4:8])

	// The destination SSRC must be 0
	 := binary.BigEndian.Uint32([8:12])
	if  != 0 {
		return errSSRCMustBeZero
	}

	// REMB rules all around me
	if !bytes.Equal([12:16], []byte{'R', 'E', 'M', 'B'}) {
		return errMissingREMBidentifier
	}

	// The next byte is the number of SSRC entries at the end.
	 := int([16])

	// Now we know the expected size, make sure they match.
	if  != 20+4* {
		return errSSRCNumAndLengthMismatch
	}

	// Get the 6-bit exponent value.
	 := [17] >> 2
	 += 127 // bias for IEEE754
	 += 23  // IEEE754 biases the decimal to the left, abs-send-time biases it to the right

	// The remaining 2-bits plus the next 16-bits are the mantissa.
	 := uint32([17]&3)<<16 | uint32([18])<<8 | uint32([19])

	if  != 0 {
		// ieee754 requires an implicit leading bit
		for ( & ( + 1)) == 0 {
			--
			 *= 2
		}
	}

	// bitrate = mantissa * 2^exp
	.Bitrate = math.Float32frombits((uint32() << 23) | ( & ))

	// Clear any existing SSRCs
	.SSRCs = nil

	// Loop over and parse the SSRC entires at the end.
	// We already verified that size == num * 4
	for  := 20;  < ;  += 4 {
		 := binary.BigEndian.Uint32([ : +4])
		.SSRCs = append(.SSRCs, )
	}

	return nil
}

// Header returns the Header associated with this packet.
func ( *ReceiverEstimatedMaximumBitrate) () Header {
	return Header{
		Count:  FormatREMB,
		Type:   TypePayloadSpecificFeedback,
		Length: uint16((.MarshalSize() / 4) - 1),
	}
}

// String prints the REMB packet in a human-readable format.
func ( *ReceiverEstimatedMaximumBitrate) () string {
	// Keep a table of powers to units for fast conversion.
	 := []string{"b", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb"}

	// Do some unit conversions because b/s is far too difficult to read.
	 := .Bitrate
	 := 0

	// Keep dividing the bitrate until it's under 1000
	for  >= 1000.0 &&  < len() {
		 /= 1000.0
		++
	}

	 := []

	return fmt.Sprintf("ReceiverEstimatedMaximumBitrate %x %.2f %s/s", .SenderSSRC, , )
}

// DestinationSSRC returns an array of SSRC values that this packet refers to.
func ( *ReceiverEstimatedMaximumBitrate) () []uint32 {
	return .SSRCs
}