package audio

import (
	"context"
	"github.com/gopxl/beep/v2"
	"github.com/gopxl/beep/v2/mp3"
	"github.com/gopxl/beep/v2/speaker"
	"github.com/gopxl/beep/v2/wav"
	"go.uber.org/zap"
	"io"
	"time"
)

var DefaultSampleRate = beep.SampleRate(44100)

func init() {
	err := speaker.Init(DefaultSampleRate, DefaultSampleRate.N(time.Second/10))
	if err != nil {
		panic("扬声器初始化异常: " + err.Error())
	}
	zap.S().Infoln("扬声器初始化完成")
}

func PlayWav(c context.Context, r io.Reader) {
	zap.S().Debugln("开始 WAV 解码")
	streamer, format, err := wav.Decode(r)
	if err != nil {
		zap.S().Errorln("WAV解码失败: ", err)
		return
	}
	defer streamer.Close()

	zap.S().Debugln("WAV解码成功，采样率:", format.SampleRate)
	s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer)

	ctrl := &beep.Ctrl{Streamer: s}
	done := make(chan struct{})
	speaker.Play(beep.Seq(ctrl, beep.Callback(func() {
		zap.S().Debugln("音频播放完成")
		close(done)
	})))

	zap.S().Debugln("等待音频播放完成...")
	for {
		select {
		case <-done:
			zap.S().Infoln("音频播放正常结束")
			return
		case <-c.Done():
			{
				zap.S().Infoln("音频播放被 context 取消")
				speaker.Lock()
				ctrl.Streamer = nil
				speaker.Unlock()
				return
			}
		}
	}
}

func PlayMP3(c context.Context, r io.ReadCloser) {
	streamer, format, err := mp3.Decode(r)
	if err != nil {
		zap.S().Errorln("MP3解码失败: ", err)
		return
	}
	defer streamer.Close()

	s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer)

	ctrl := &beep.Ctrl{Streamer: s}
	done := make(chan struct{})
	speaker.Play(beep.Seq(ctrl, beep.Callback(func() {
		close(done)
	})))

	for {
		select {
		case <-done:
			return
		case <-c.Done():
			{
				speaker.Lock()
				ctrl.Streamer = nil
				speaker.Unlock()
				return
			}
		}
	}
}
