-- | Transport abstraction for libp2p.
--
-- Defines the record-of-functions pattern for transport-agnostic
-- connection management. Each transport (TCP, QUIC, etc.) provides
-- a Transport value with dial/listen/canDial implementations.
module Network.LibP2P.Transport.Transport
  ( RawConnection (..)
  , Listener (..)
  , Transport (..)
  ) where

import Network.LibP2P.Multiaddr.Multiaddr (Multiaddr)
import Network.LibP2P.MultistreamSelect.Negotiation (StreamIO (..))

-- | A raw (unencrypted, un-muxed) connection from a transport.
-- Provides byte-level I/O via StreamIO, plus address info and cleanup.
data RawConnection = RawConnection
  { RawConnection -> StreamIO
rcStreamIO :: !StreamIO -- ^ Byte-level read/write over the connection
  , RawConnection -> Multiaddr
rcLocalAddr :: !Multiaddr -- ^ Local multiaddr (e.g. /ip4/127.0.0.1/tcp/12345)
  , RawConnection -> Multiaddr
rcRemoteAddr :: !Multiaddr -- ^ Remote multiaddr
  , RawConnection -> IO ()
rcClose :: !(IO ()) -- ^ Close the underlying transport connection
  }

-- | A listener that accepts inbound connections.
data Listener = Listener
  { Listener -> IO RawConnection
listenerAccept :: !(IO RawConnection) -- ^ Block until a connection arrives
  , Listener -> IO ()
listenerClose :: !(IO ()) -- ^ Stop listening and close the socket
  , Listener -> Multiaddr
listenerAddr :: !Multiaddr -- ^ Actual bound address (port 0 resolves here)
  }

-- | Transport provides dial/listen capabilities for a specific protocol.
data Transport = Transport
  { Transport -> Multiaddr -> IO RawConnection
transportDial :: !(Multiaddr -> IO RawConnection) -- ^ Dial a remote peer
  , Transport -> Multiaddr -> IO Listener
transportListen :: !(Multiaddr -> IO Listener) -- ^ Listen for inbound connections
  , Transport -> Multiaddr -> Bool
transportCanDial :: !(Multiaddr -> Bool) -- ^ Check if this transport can handle the address
  }