{-# LANGUAGE TypeFamilies #-}
module Metro.TP.TCPSocket
  ( TCPSocket
  , tcpSocket
  , tcpSocket_
  ) where

import           Metro.Class               (Transport (..))
import           Metro.Socket              (connect)
import           Network.Socket            (Socket, close)
import           Network.Socket.ByteString (recv, sendAll)

newtype TCPSocket = TCPSocket Socket

instance Transport TCPSocket where
  data TransportConfig TCPSocket =
      RawSocket Socket
    | SocketUri String
  newTransport :: TransportConfig TCPSocket -> IO TCPSocket
newTransport (RawSocket soc) = TCPSocket -> IO TCPSocket
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TCPSocket -> IO TCPSocket) -> TCPSocket -> IO TCPSocket
forall a b. (a -> b) -> a -> b
$ Socket -> TCPSocket
TCPSocket Socket
soc
  newTransport (SocketUri h)   = Socket -> TCPSocket
TCPSocket (Socket -> TCPSocket) -> IO Socket -> IO TCPSocket
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Socket
connect String
h
  recvData :: TCPSocket -> Int -> IO ByteString
recvData (TCPSocket Socket
soc) = Socket -> Int -> IO ByteString
recv Socket
soc
  sendData :: TCPSocket -> ByteString -> IO ()
sendData (TCPSocket Socket
soc) = Socket -> ByteString -> IO ()
sendAll Socket
soc
  closeTransport :: TCPSocket -> IO ()
closeTransport (TCPSocket Socket
soc) = Socket -> IO ()
close Socket
soc

tcpSocket_ :: Socket -> TransportConfig TCPSocket
tcpSocket_ :: Socket -> TransportConfig TCPSocket
tcpSocket_ = Socket -> TransportConfig TCPSocket
RawSocket

tcpSocket :: String -> TransportConfig TCPSocket
tcpSocket :: String -> TransportConfig TCPSocket
tcpSocket = String -> TransportConfig TCPSocket
SocketUri