package alsa

import (
	"fmt"

	"github.com/AlexxIT/go2rtc/pkg/alsa/device"
	"github.com/AlexxIT/go2rtc/pkg/core"
	"github.com/AlexxIT/go2rtc/pkg/pcm"
	"github.com/pion/rtp"
)

type Playback struct {
	core.Connection
	dev    *device.Device
	closed core.Waiter
}

func newPlayback(dev *device.Device) (*Playback, error) {
	medias := []*core.Media{
		{
			Kind:      core.KindAudio,
			Direction: core.DirectionSendonly,
			Codecs: []*core.Codec{
				{Name: core.CodecPCML},                  // support ffmpeg producer (auto transcode)
				{Name: core.CodecPCMA, ClockRate: 8000}, // support webrtc producer
			},
		},
	}
	return &Playback{
		Connection: core.Connection{
			ID:         core.NewID(),
			FormatName: "alsa",
			Medias:     medias,
			Transport:  dev,
		},
		dev: dev,
	}, nil
}

func (p *Playback) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
	return nil, core.ErrCantGetTrack
}

func (p *Playback) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error {
	src := track.Codec
	dst := &core.Codec{
		Name:      core.CodecPCML,
		ClockRate: p.dev.GetRateNear(src.ClockRate),
		Channels:  p.dev.GetChannelsNear(src.Channels),
	}
	sender := core.NewSender(media, dst)

	sender.Handler = func(pkt *rtp.Packet) {
		if n, err := p.dev.Write(pkt.Payload); err == nil {
			p.Send += n
		}
	}

	if sender.Handler = pcm.TranscodeHandler(dst, src, sender.Handler); sender.Handler == nil {
		return fmt.Errorf("alsa: can't convert %s to %s", src, dst)
	}

	// typical card support:
	// - Formats: S16_LE, S32_LE
	// - ClockRates: 8000 - 192000
	// - Channels: 2 - 10
	err := p.dev.SetHWParams(device.SNDRV_PCM_FORMAT_S16_LE, dst.ClockRate, byte(dst.Channels))
	if err != nil {
		return err
	}

	sender.HandleRTP(track)
	p.Senders = append(p.Senders, sender)
	return nil
}

func (p *Playback) Start() (err error) {
	return p.closed.Wait()
}

func (p *Playback) Stop() error {
	p.closed.Done(nil)
	return p.Connection.Stop()
}
