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

package rtcp

import (
	
	
)

// A FIREntry is a (SSRC, seqno) pair, as carried by FullIntraRequest.
type FIREntry struct {
	SSRC           uint32
	SequenceNumber uint8
}

// The FullIntraRequest packet is used to reliably request an Intra frame
// in a video stream.  See RFC 5104 Section 3.5.1.  This is not for loss
// recovery, which should use PictureLossIndication (PLI) instead.
type FullIntraRequest struct {
	SenderSSRC uint32
	MediaSSRC  uint32

	FIR []FIREntry
}

const (
	firOffset = 8
)

var _ Packet = (*FullIntraRequest)(nil)

// Marshal encodes the FullIntraRequest
func ( FullIntraRequest) () ([]byte, error) {
	 := make([]byte, firOffset+(len(.FIR)*8))
	binary.BigEndian.PutUint32(, .SenderSSRC)
	binary.BigEndian.PutUint32([4:], .MediaSSRC)
	for ,  := range .FIR {
		binary.BigEndian.PutUint32([firOffset+8*:], .SSRC)
		[firOffset+8*+4] = .SequenceNumber
	}
	 := .Header()
	,  := .Marshal()
	if  != nil {
		return nil, 
	}

	return append(, ...), nil
}

// Unmarshal decodes the TransportLayerNack
func ( *FullIntraRequest) ( []byte) error {
	if len() < (headerLength + ssrcLength) {
		return errPacketTooShort
	}

	var  Header
	if  := .Unmarshal();  != nil {
		return 
	}

	if len() < (headerLength + int(4*.Length)) {
		return errPacketTooShort
	}

	if .Type != TypePayloadSpecificFeedback || .Count != FormatFIR {
		return errWrongType
	}

	// The FCI field MUST contain one or more FIR entries
	if 4*.Length-firOffset <= 0 || (4*.Length)%8 != 0 {
		return errBadLength
	}

	.SenderSSRC = binary.BigEndian.Uint32([headerLength:])
	.MediaSSRC = binary.BigEndian.Uint32([headerLength+ssrcLength:])
	for  := headerLength + firOffset;  < (headerLength + int(.Length*4));  += 8 {
		.FIR = append(.FIR, FIREntry{
			binary.BigEndian.Uint32([:]),
			[+4],
		})
	}
	return nil
}

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

// MarshalSize returns the size of the packet once marshaled
func ( *FullIntraRequest) () int {
	return headerLength + firOffset + len(.FIR)*8
}

func ( *FullIntraRequest) () string {
	 := fmt.Sprintf("FullIntraRequest %x %x",
		.SenderSSRC, .MediaSSRC)
	for ,  := range .FIR {
		 += fmt.Sprintf(" (%x %v)", .SSRC, .SequenceNumber)
	}
	return 
}

// DestinationSSRC returns an array of SSRC values that this packet refers to.
func ( *FullIntraRequest) () []uint32 {
	 := make([]uint32, 0, len(.FIR))
	for ,  := range .FIR {
		 = append(, .SSRC)
	}
	return 
}