package mpegts

import (
	"bytes"
	"testing"

	"github.com/stretchr/testify/require"
)

var opusAccessUnitCases = []struct {
	name string
	dec  opusAccessUnit
	enc  []byte
}{
	{
		"a",
		opusAccessUnit{
			ControlHeader: opusControlHeader{
				PayloadSize:            123,
				StartTrimFlag:          true,
				ControlExtensionFlag:   true,
				StartTrim:              20,
				ControlExtensionLength: 40,
			},
			Packet: bytes.Repeat([]byte{1}, 123),
		},
		[]byte{
			0x7f, 0xf4, 0x7b, 0x00, 0x14, 0x28, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01,
		},
	},
}

func TestOpusAccessUnitMarshal(t *testing.T) {
	for _, ca := range opusAccessUnitCases {
		t.Run(ca.name, func(t *testing.T) {
			s := ca.dec.marshalSize()
			buf := make([]byte, s)
			n, err := ca.dec.marshalTo(buf)
			require.NoError(t, err)
			require.Equal(t, s, n)
			require.Equal(t, ca.enc, buf)
		})
	}
}

func TestOpusAccessUnitUnmarshal(t *testing.T) {
	for _, ca := range opusAccessUnitCases {
		t.Run(ca.name, func(t *testing.T) {
			var h opusAccessUnit
			_, err := h.unmarshal(ca.enc)
			require.NoError(t, err)
			require.Equal(t, ca.dec, h)
		})
	}
}

func FuzzOpusAccessUnitUnmarshal(f *testing.F) {
	for _, ca := range opusAccessUnitCases {
		f.Add(ca.enc)
	}

	f.Fuzz(func(t *testing.T, b []byte) {
		var h opusAccessUnit
		_, err := h.unmarshal(b)
		if err != nil {
			return
		}

		buf := make([]byte, h.marshalSize())
		_, err = h.marshalTo(buf)
		require.NoError(t, err)
	})
}
