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

package rtcp

import (
	
	
)

// The Goodbye packet indicates that one or more sources are no longer active.
type Goodbye struct {
	// The SSRC/CSRC identifiers that are no longer active
	Sources []uint32
	// Optional text indicating the reason for leaving, e.g., "camera malfunction" or "RTP loop detected"
	Reason string
}

// Marshal encodes the Goodbye packet in binary
func ( Goodbye) () ([]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|    SC   |   PT=BYE=203  |             length            |
	 *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *       |                           SSRC/CSRC                           |
	 *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *       :                              ...                              :
	 *       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
	 * (opt) |     length    |               reason for leaving            ...
	 *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 */

	 := make([]byte, .MarshalSize())
	 := [headerLength:]

	if len(.Sources) > countMax {
		return nil, errTooManySources
	}

	for ,  := range .Sources {
		binary.BigEndian.PutUint32([*ssrcLength:], )
	}

	if .Reason != "" {
		 := []byte(.Reason)

		if len() > sdesMaxOctetCount {
			return nil, errReasonTooLong
		}

		 := len(.Sources) * ssrcLength
		[] = uint8(len())
		copy([+1:], )
	}

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

	return , nil
}

// Unmarshal decodes the Goodbye packet from binary
func ( *Goodbye) ( []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|    SC   |   PT=BYE=203  |             length            |
	 *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *       |                           SSRC/CSRC                           |
	 *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *       :                              ...                              :
	 *       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
	 * (opt) |     length    |               reason for leaving            ...
	 *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 */

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

	if .Type != TypeGoodbye {
		return errWrongType
	}

	if getPadding(len()) != 0 {
		return errPacketTooShort
	}

	.Sources = make([]uint32, .Count)

	 := int(headerLength + .Count*ssrcLength)
	if  > len() {
		return errPacketTooShort
	}

	for  := 0;  < int(.Count); ++ {
		 := headerLength + *ssrcLength

		.Sources[] = binary.BigEndian.Uint32([:])
	}

	if  < len() {
		 := int([])
		 :=  + 1 + 

		if  > len() {
			return errPacketTooShort
		}

		.Reason = string([+1 : ])
	}

	return nil
}

// Header returns the Header associated with this packet.
func ( *Goodbye) () Header {
	return Header{
		Padding: false,
		Count:   uint8(len(.Sources)),
		Type:    TypeGoodbye,
		Length:  uint16((.MarshalSize() / 4) - 1),
	}
}

// MarshalSize returns the size of the packet once marshaled
func ( *Goodbye) () int {
	 := len(.Sources) * ssrcLength
	// reason is optional
	 := len(.Reason)
	if  > 0 {
		++
	}

	 := headerLength +  + 

	// align to 32-bit boundary
	return  + getPadding()
}

// DestinationSSRC returns an array of SSRC values that this packet refers to.
func ( *Goodbye) () []uint32 {
	 := make([]uint32, len(.Sources))
	copy(, .Sources)
	return 
}

func ( Goodbye) () string {
	 := "Goodbye\n"
	for ,  := range .Sources {
		 += fmt.Sprintf("\tSource %d: %x\n", , )
	}
	 += fmt.Sprintf("\tReason: %s\n", .Reason)

	return 
}