package decoder

import (
	"context"
	"fmt"
	"io"
	"strings"

	"github.com/jan/fm-rds-tx/internal/ingest"
)

var ErrUnsupported = fmt.Errorf("decoder unsupported")

type StreamMeta struct {
	ContentType  string
	SampleRateHz int
	Channels     int
	SourceID     string
}

type Decoder interface {
	Name() string
	DecodeStream(ctx context.Context, r io.Reader, meta StreamMeta, emit func(ingest.PCMChunk) error) error
}

type Builder func() Decoder

type Registry struct {
	byName map[string]Builder
}

func NewRegistry() *Registry {
	return &Registry{byName: map[string]Builder{}}
}

func (r *Registry) Register(name string, builder Builder) {
	if r == nil || builder == nil {
		return
	}
	r.byName[strings.ToLower(strings.TrimSpace(name))] = builder
}

func (r *Registry) Create(name string) (Decoder, error) {
	if r == nil {
		return nil, fmt.Errorf("%w: registry nil", ErrUnsupported)
	}
	builder, ok := r.byName[strings.ToLower(strings.TrimSpace(name))]
	if !ok {
		return nil, fmt.Errorf("%w: %s", ErrUnsupported, name)
	}
	return builder(), nil
}

func (r *Registry) SelectByContentType(contentType string) (Decoder, error) {
	ct := strings.ToLower(strings.TrimSpace(contentType))
	switch {
	case strings.Contains(ct, "mpeg"), strings.Contains(ct, "mp3"):
		return r.Create("mp3")
	case strings.Contains(ct, "ogg"), strings.Contains(ct, "vorbis"):
		return r.Create("oggvorbis")
	case strings.Contains(ct, "aac"), strings.Contains(ct, "adts"):
		return r.Create("aac")
	default:
		return nil, fmt.Errorf("%w: content-type=%s", ErrUnsupported, contentType)
	}
}
