module Nbparts.Run
  ( Options (..),
    Command (..),
    run,
  )
where

import Control.Monad.Error.Class (MonadError, throwError)
import Control.Monad.Except (ExceptT, runExceptT, withExceptT)
import Control.Monad.IO.Class (MonadIO)
import Nbparts.Pack (PackOptions)
import Nbparts.Pack qualified as Nbparts
import Nbparts.Types (NbpartsError (PackError, UnpackError))
import Nbparts.Unpack (UnpackOptions)
import Nbparts.Unpack qualified as Nbparts

newtype Options = Options
  { Options -> Command
command :: Command
  }

data Command = Unpack UnpackOptions | Pack PackOptions

run :: (MonadError NbpartsError m, MonadIO m) => Options -> m ()
run :: forall (m :: * -> *).
(MonadError NbpartsError m, MonadIO m) =>
Options -> m ()
run (Options Command
command) = case Command
command of
  Unpack UnpackOptions
unpackOpts -> (UnpackError -> NbpartsError) -> ExceptT UnpackError m () -> m ()
forall e' (m :: * -> *) e a.
MonadError e' m =>
(e -> e') -> ExceptT e m a -> m a
hoistError UnpackError -> NbpartsError
UnpackError (ExceptT UnpackError m () -> m ())
-> ExceptT UnpackError m () -> m ()
forall a b. (a -> b) -> a -> b
$ UnpackOptions -> ExceptT UnpackError m ()
forall (m :: * -> *).
(MonadError UnpackError m, MonadIO m) =>
UnpackOptions -> m ()
Nbparts.unpack UnpackOptions
unpackOpts
  Pack PackOptions
packOpts -> (PackError -> NbpartsError) -> ExceptT PackError m () -> m ()
forall e' (m :: * -> *) e a.
MonadError e' m =>
(e -> e') -> ExceptT e m a -> m a
hoistError PackError -> NbpartsError
PackError (ExceptT PackError m () -> m ()) -> ExceptT PackError m () -> m ()
forall a b. (a -> b) -> a -> b
$ PackOptions -> ExceptT PackError m ()
forall (m :: * -> *).
(MonadError PackError m, MonadIO m) =>
PackOptions -> m ()
Nbparts.pack PackOptions
packOpts

hoistError :: (MonadError e' m) => (e -> e') -> ExceptT e m a -> m a
hoistError :: forall e' (m :: * -> *) e a.
MonadError e' m =>
(e -> e') -> ExceptT e m a -> m a
hoistError e -> e'
mapErr ExceptT e m a
action = do
  Either e' a
res <- ExceptT e' m a -> m (Either e' a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT e' m a -> m (Either e' a))
-> ExceptT e' m a -> m (Either e' a)
forall a b. (a -> b) -> a -> b
$ (e -> e') -> ExceptT e m a -> ExceptT e' m a
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT e -> e'
mapErr ExceptT e m a
action
  case Either e' a
res of
    Right a
value -> a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
value
    Left e'
err -> e' -> m a
forall a. e' -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError e'
err