package iroh

import (
	

	
	
)

// CustomDatagram is one datagram received by a [CustomTransport].
type CustomDatagram struct {
	Remote   netaddr.CustomAddr
	Local    netaddr.CustomAddr
	HasLocal bool
	Data     []byte
}

// CustomTransport is a pluggable endpoint transport for custom addresses.
// Implementations own their wire format and exchange datagrams using
// [netaddr.CustomAddr] values advertised in endpoint addresses.
type CustomTransport interface {
	// Serve runs the transport until ctx is done. Each received datagram should
	// be passed to recv. recv reports false when the endpoint is shutting down or
	// its receive queue is full.
	Serve(ctx context.Context, recv func(CustomDatagram) bool)

	// Send sends p to remote. local is nil when qng did not select a specific
	// local custom address for the path.
	Send(remote netaddr.CustomAddr, local *netaddr.CustomAddr, p []byte) bool
}

// AdvertisingCustomTransport is a custom transport that can publish local
// addresses in [Endpoint.Addr] and [Endpoint.WatchAddr].
//
// Existing [CustomTransport] implementations do not need to implement this
// interface. Transports that do implement it must return only address material
// that peers can dial through the same transport id.
type AdvertisingCustomTransport interface {
	CustomTransport

	// LocalCustomAddrs returns the local custom addresses this endpoint should
	// advertise. The returned slice is copied by the endpoint.
	LocalCustomAddrs(context.Context) ([]netaddr.CustomAddr, error)
}

type customTransportAdapter struct {
	t CustomTransport
}

func ( customTransportAdapter) ( context.Context,  func(socket.CustomDatagram) bool) {
	.t.Serve(, func( CustomDatagram) bool {
		return (socket.CustomDatagram{
			Remote:   .Remote,
			Local:    .Local,
			HasLocal: .HasLocal,
			Data:     .Data,
		})
	})
}

func ( customTransportAdapter) ( netaddr.CustomAddr,  *netaddr.CustomAddr,  []byte) bool {
	return .t.Send(, , )
}

func customTransportAdapters( []CustomTransport) []socket.CustomTransport {
	if len() == 0 {
		return nil
	}
	 := make([]socket.CustomTransport, 0, len())
	for ,  := range  {
		if  != nil {
			 = append(, customTransportAdapter{t: })
		}
	}
	return 
}

func customTransportLocalAddrs( context.Context,  []CustomTransport) []netaddr.CustomAddr {
	var  []netaddr.CustomAddr
	for ,  := range  {
		,  := .(AdvertisingCustomTransport)
		if ! {
			continue
		}
		,  := .LocalCustomAddrs()
		if  != nil {
			continue
		}
		 = append(, ...)
	}
	return 
}