// Package direct provides a pass-through link implementation above transports.
package direct

import (
	"context"
	"fmt"

	"github.com/openlibrecommunity/olcrtc/internal/link"
	"github.com/openlibrecommunity/olcrtc/internal/transport"
)

type directLink struct {
	transport transport.Transport
}

// New creates a direct link that forwards bytes to the selected transport.
func New(ctx context.Context, cfg link.Config) (link.Link, error) {
	tr, err := transport.New(ctx, cfg.Transport, transport.Config{
		Carrier:         cfg.Carrier,
		RoomURL:         cfg.RoomURL,
		Engine:          cfg.Engine,
		URL:             cfg.URL,
		Token:           cfg.Token,
		DeviceID:        cfg.DeviceID,
		Name:            cfg.Name,
		OnData:          cfg.OnData,
		DNSServer:       cfg.DNSServer,
		ProxyAddr:       cfg.ProxyAddr,
		ProxyPort:       cfg.ProxyPort,
		VideoWidth:      cfg.VideoWidth,
		VideoHeight:     cfg.VideoHeight,
		VideoFPS:        cfg.VideoFPS,
		VideoBitrate:    cfg.VideoBitrate,
		VideoHW:         cfg.VideoHW,
		VideoQRSize:     cfg.VideoQRSize,
		VideoQRRecovery: cfg.VideoQRRecovery,
		VideoCodec:      cfg.VideoCodec,
		VideoTileModule: cfg.VideoTileModule,
		VideoTileRS:     cfg.VideoTileRS,
		VP8FPS:          cfg.VP8FPS,
		VP8BatchSize:    cfg.VP8BatchSize,
		SEIFPS:          cfg.SEIFPS,
		SEIBatchSize:    cfg.SEIBatchSize,
		SEIFragmentSize: cfg.SEIFragmentSize,
		SEIAckTimeoutMS: cfg.SEIAckTimeoutMS,
	})
	if err != nil {
		return nil, fmt.Errorf("create transport for direct link: %w", err)
	}

	return &directLink{transport: tr}, nil
}

func (d *directLink) Connect(ctx context.Context) error {
	if err := d.transport.Connect(ctx); err != nil {
		return fmt.Errorf("transport connect: %w", err)
	}
	return nil
}

func (d *directLink) Send(data []byte) error {
	if err := d.transport.Send(data); err != nil {
		return fmt.Errorf("transport send: %w", err)
	}
	return nil
}

func (d *directLink) Close() error {
	if err := d.transport.Close(); err != nil {
		return fmt.Errorf("transport close: %w", err)
	}
	return nil
}

func (d *directLink) SetReconnectCallback(cb func())    { d.transport.SetReconnectCallback(cb) }
func (d *directLink) SetShouldReconnect(fn func() bool) { d.transport.SetShouldReconnect(fn) }
func (d *directLink) SetEndedCallback(cb func(string))  { d.transport.SetEndedCallback(cb) }
func (d *directLink) WatchConnection(ctx context.Context) {
	d.transport.WatchConnection(ctx)
}
func (d *directLink) CanSend() bool { return d.transport.CanSend() }
