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

package rtcp

import (
	
)

// ApplicationDefined represents an RTCP application-defined packet.
type ApplicationDefined struct {
	SubType uint8
	SSRC    uint32
	Name    string
	Data    []byte
}

// DestinationSSRC returns the SSRC value for this packet.
func ( ApplicationDefined) () []uint32 {
	return []uint32{.SSRC}
}

// Marshal serializes the application-defined struct into a byte slice with padding.
func ( ApplicationDefined) () ([]byte, error) {
	 := len(.Data)
	if  > 0xFFFF-12 {
		return nil, errAppDefinedDataTooLarge
	}
	if len(.Name) != 4 {
		return nil, errAppDefinedInvalidName
	}
	// Calculate the padding size to be added to make the packet length a multiple of 4 bytes.
	 := 4 - ( % 4)
	if  == 4 {
		 = 0
	}

	 := .MarshalSize()
	 := Header{
		Type:    TypeApplicationDefined,
		Length:  uint16(( / 4) - 1),
		Padding:  != 0,
		Count:   .SubType,
	}

	,  := .Marshal()
	if  != nil {
		return nil, 
	}

	 := make([]byte, )
	copy(, )
	binary.BigEndian.PutUint32([4:8], .SSRC)
	copy([8:12], .Name)
	copy([12:], .Data)

	// Add padding if necessary.
	if  > 0 {
		for  := 0;  < ; ++ {
			[12++] = byte()
		}
	}

	return , nil
}

// Unmarshal parses the given raw packet into an application-defined struct, handling padding.
func ( *ApplicationDefined) ( []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
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |V=2|P| subtype |   PT=APP=204  |             length            |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                           SSRC/CSRC                           |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                          name (ASCII)                         |
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |                   application-dependent data                ...
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	*/
	 := Header{}
	 := .Unmarshal()
	if  != nil {
		return 
	}
	if len() < 12 {
		return errPacketTooShort
	}

	if int(.Length+1)*4 != len() {
		return errAppDefinedInvalidLength
	}

	.SubType = .Count
	.SSRC = binary.BigEndian.Uint32([4:8])
	.Name = string([8:12])

	// Check for padding.
	 := 0
	if .Padding {
		 = int([len()-1])
		if  > len()-12 {
			return errWrongPadding
		}
	}

	.Data = [12 : len()-]

	return nil
}

// MarshalSize returns the size of the packet once marshaled
func ( *ApplicationDefined) () int {
	 := len(.Data)
	// Calculate the padding size to be added to make the packet length a multiple of 4 bytes.
	 := 4 - ( % 4)
	if  == 4 {
		 = 0
	}
	return 12 +  + 
}