module Sarsi where

import Crypto.Hash (Digest, hash)
import Crypto.Hash.Algorithms (MD5)
import qualified Data.ByteString.Char8 as BSC8
import Network.Socket (Family (AF_UNIX), SockAddr (SockAddrUnix), Socket, SocketType (Stream), defaultProtocol, socket)
import System.Directory (XdgDirectory (XdgCache), createDirectory, doesDirectoryExist, doesFileExist, getXdgDirectory, makeAbsolute, removeFile)
import System.FilePath ((</>))

title :: String
title :: String
title = String
"sarsi"

newtype Broker = Broker FilePath

data Topic = Topic Broker FilePath

getBroker :: IO Broker
getBroker :: IO Broker
getBroker = do
  String
bp <- XdgDirectory -> String -> IO String
getXdgDirectory XdgDirectory
XdgCache String
title
  let broker :: Broker
broker = String -> Broker
Broker String
bp
  Bool
exists <- String -> IO Bool
doesDirectoryExist String
bp
  if Bool
exists then Broker -> IO Broker
forall (m :: * -> *) a. Monad m => a -> m a
return Broker
broker else String -> IO ()
createDirectory String
bp IO () -> IO Broker -> IO Broker
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Broker -> IO Broker
forall (m :: * -> *) a. Monad m => a -> m a
return Broker
broker

getTopic :: Broker -> FilePath -> IO Topic
getTopic :: Broker -> String -> IO Topic
getTopic b :: Broker
b@(Broker String
bp) String
fp' = do
  String
fp <- String -> IO String
makeAbsolute String
fp'
  Topic -> IO Topic
forall (m :: * -> *) a. Monad m => a -> m a
return (Topic -> IO Topic) -> Topic -> IO Topic
forall a b. (a -> b) -> a -> b
$ Broker -> String -> Topic
Topic Broker
b (String -> Topic) -> String -> Topic
forall a b. (a -> b) -> a -> b
$ String
bp String -> String -> String
</> (Digest MD5 -> String
forall a. Show a => a -> String
show (Digest MD5 -> String) -> Digest MD5 -> String
forall a b. (a -> b) -> a -> b
$ (ByteString -> Digest MD5
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
hash (ByteString -> Digest MD5) -> ByteString -> Digest MD5
forall a b. (a -> b) -> a -> b
$ String -> ByteString
BSC8.pack String
fp :: Digest MD5))

removeTopic :: Topic -> IO ()
removeTopic :: Topic -> IO ()
removeTopic (Topic Broker
_ String
fp) = String -> IO ()
removeFile String
fp

createSocket :: IO Socket
createSocket :: IO Socket
createSocket = do
  Family -> SocketType -> ProtocolNumber -> IO Socket
socket Family
AF_UNIX SocketType
Stream ProtocolNumber
defaultProtocol

createSockAddr :: Topic -> IO SockAddr
createSockAddr :: Topic -> IO SockAddr
createSockAddr t :: Topic
t@(Topic Broker
_ String
path) = do
  Bool
exists <- String -> IO Bool
doesFileExist String
path
  if (Bool
exists) then String -> IO ()
removeFile String
path else () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  SockAddr -> IO SockAddr
forall (m :: * -> *) a. Monad m => a -> m a
return (SockAddr -> IO SockAddr) -> SockAddr -> IO SockAddr
forall a b. (a -> b) -> a -> b
$ Topic -> SockAddr
getSockAddr Topic
t

getSockAddr :: Topic -> SockAddr
getSockAddr :: Topic -> SockAddr
getSockAddr (Topic Broker
_ String
path) = String -> SockAddr
SockAddrUnix String
path