-- | Provides a dynamic effect for writing files.
--
-- @since 0.1
module Effectful.FileSystem.FileWriter.Dynamic
  ( -- * Effect
    FileWriter (..),
    writeBinaryFile,
    appendBinaryFile,

    -- ** Handlers
    runFileWriter,

    -- * UTF-8 Utils
    writeFileUtf8,
    appendFileUtf8,

    -- * Re-exports
    ByteString,
    OsPath,
    Text,
  )
where

import Data.ByteString (ByteString)
import Data.Text (Text)
import Effectful
  ( Dispatch (Dynamic),
    DispatchOf,
    Eff,
    Effect,
    IOE,
    type (:>),
  )
import Effectful.Dispatch.Dynamic (HasCallStack, reinterpret_, send)
import Effectful.Dynamic.Utils (ShowEffect (showEffectCons))
import Effectful.FileSystem.FileWriter.Static qualified as Static
import FileSystem.OsPath (OsPath)
import FileSystem.UTF8 qualified as FS.UTF8

-- | Dynamic effect for reading files.
--
-- @since 0.1
data FileWriter :: Effect where
  WriteBinaryFile :: OsPath -> ByteString -> FileWriter m ()
  AppendBinaryFile :: OsPath -> ByteString -> FileWriter m ()

-- | @since 0.1
type instance DispatchOf FileWriter = Dynamic

-- | @since 0.1
instance ShowEffect FileWriter where
  showEffectCons :: forall (m :: * -> *) a. FileWriter m a -> String
showEffectCons = \case
    WriteBinaryFile OsPath
_ ByteString
_ -> String
"WriteBinaryFile"
    AppendBinaryFile OsPath
_ ByteString
_ -> String
"AppendBinaryFile"

-- | Runs 'FileWriter' in 'IO'.
--
-- @since 0.1
runFileWriter ::
  ( HasCallStack,
    IOE :> es
  ) =>
  Eff (FileWriter : es) a ->
  Eff es a
runFileWriter :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, IOE :> es) =>
Eff (FileWriter : es) a -> Eff es a
runFileWriter = (Eff (FileWriter : es) a -> Eff es a)
-> EffectHandler_ FileWriter (FileWriter : es)
-> Eff (FileWriter : es) a
-> Eff es a
forall (e :: (* -> *) -> * -> *)
       (handlerEs :: [(* -> *) -> * -> *]) a (es :: [(* -> *) -> * -> *])
       b.
(HasCallStack, DispatchOf e ~ 'Dynamic) =>
(Eff handlerEs a -> Eff es b)
-> EffectHandler_ e handlerEs -> Eff (e : es) a -> Eff es b
reinterpret_ Eff (FileWriter : es) a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, IOE :> es) =>
Eff (FileWriter : es) a -> Eff es a
Static.runFileWriter (EffectHandler_ FileWriter (FileWriter : es)
 -> Eff (FileWriter : es) a -> Eff es a)
-> EffectHandler_ FileWriter (FileWriter : es)
-> Eff (FileWriter : es) a
-> Eff es a
forall a b. (a -> b) -> a -> b
$ \case
  WriteBinaryFile OsPath
p ByteString
bs -> OsPath -> ByteString -> Eff (FileWriter : es) ()
forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> ByteString -> Eff es ()
Static.writeBinaryFile OsPath
p ByteString
bs
  AppendBinaryFile OsPath
p ByteString
bs -> OsPath -> ByteString -> Eff (FileWriter : es) ()
forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> ByteString -> Eff es ()
Static.appendBinaryFile OsPath
p ByteString
bs

-- | @since 0.1
writeBinaryFile ::
  ( FileWriter :> es,
    HasCallStack
  ) =>
  OsPath ->
  ByteString ->
  Eff es ()
writeBinaryFile :: forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> ByteString -> Eff es ()
writeBinaryFile OsPath
p = FileWriter (Eff es) () -> Eff es ()
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (FileWriter (Eff es) () -> Eff es ())
-> (ByteString -> FileWriter (Eff es) ())
-> ByteString
-> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> ByteString -> FileWriter (Eff es) ()
forall (m :: * -> *). OsPath -> ByteString -> FileWriter m ()
WriteBinaryFile OsPath
p

-- | @since 0.1
appendBinaryFile ::
  ( FileWriter :> es,
    HasCallStack
  ) =>
  OsPath ->
  ByteString ->
  Eff es ()
appendBinaryFile :: forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> ByteString -> Eff es ()
appendBinaryFile OsPath
p = FileWriter (Eff es) () -> Eff es ()
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (FileWriter (Eff es) () -> Eff es ())
-> (ByteString -> FileWriter (Eff es) ())
-> ByteString
-> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> ByteString -> FileWriter (Eff es) ()
forall (m :: * -> *). OsPath -> ByteString -> FileWriter m ()
AppendBinaryFile OsPath
p

-- | Writes to a file.
--
-- @since 0.1
writeFileUtf8 ::
  ( FileWriter :> es,
    HasCallStack
  ) =>
  OsPath ->
  Text ->
  Eff es ()
writeFileUtf8 :: forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> Text -> Eff es ()
writeFileUtf8 OsPath
f = OsPath -> ByteString -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> ByteString -> Eff es ()
writeBinaryFile OsPath
f (ByteString -> Eff es ())
-> (Text -> ByteString) -> Text -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
FS.UTF8.encodeUtf8

-- | Appends to a file.
--
-- @since 0.1
appendFileUtf8 ::
  ( FileWriter :> es,
    HasCallStack
  ) =>
  OsPath ->
  Text ->
  Eff es ()
appendFileUtf8 :: forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> Text -> Eff es ()
appendFileUtf8 OsPath
f = OsPath -> ByteString -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(FileWriter :> es, HasCallStack) =>
OsPath -> ByteString -> Eff es ()
appendBinaryFile OsPath
f (ByteString -> Eff es ())
-> (Text -> ByteString) -> Text -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
FS.UTF8.encodeUtf8