module ServantSerf.Type.Context where

import qualified Control.Monad.Catch as Exception
import qualified ServantSerf.Exception.ExtraArgument as ExtraArgument
import qualified ServantSerf.Exception.InvalidOption as InvalidOption
import qualified ServantSerf.Exception.MissingArgument as MissingArgument
import qualified ServantSerf.Exception.UnknownOption as UnknownOption
import qualified ServantSerf.Type.Config as Config
import qualified ServantSerf.Type.Flag as Flag
import qualified System.Console.GetOpt as Console

data Context = Context
  { Context -> Config
config :: Config.Config,
    Context -> FilePath
input :: FilePath,
    Context -> FilePath
output :: FilePath,
    Context -> FilePath
source :: FilePath
  }
  deriving (Context -> Context -> Bool
(Context -> Context -> Bool)
-> (Context -> Context -> Bool) -> Eq Context
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Context -> Context -> Bool
== :: Context -> Context -> Bool
$c/= :: Context -> Context -> Bool
/= :: Context -> Context -> Bool
Eq, Int -> Context -> ShowS
[Context] -> ShowS
Context -> FilePath
(Int -> Context -> ShowS)
-> (Context -> FilePath) -> ([Context] -> ShowS) -> Show Context
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Context -> ShowS
showsPrec :: Int -> Context -> ShowS
$cshow :: Context -> FilePath
show :: Context -> FilePath
$cshowList :: [Context] -> ShowS
showList :: [Context] -> ShowS
Show)

fromArguments :: (Exception.MonadThrow m) => [String] -> m Context
fromArguments :: forall (m :: * -> *). MonadThrow m => [FilePath] -> m Context
fromArguments [FilePath]
arguments = do
  let ([Flag]
fs, [FilePath]
as, [FilePath]
us, [FilePath]
is) = ArgOrder Flag
-> [OptDescr Flag]
-> [FilePath]
-> ([Flag], [FilePath], [FilePath], [FilePath])
forall a.
ArgOrder a
-> [OptDescr a]
-> [FilePath]
-> ([a], [FilePath], [FilePath], [FilePath])
Console.getOpt' ArgOrder Flag
forall a. ArgOrder a
Console.Permute [OptDescr Flag]
Flag.options [FilePath]
arguments
  (FilePath -> m Any) -> [FilePath] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (UnknownOption -> m Any
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (UnknownOption -> m Any)
-> (FilePath -> UnknownOption) -> FilePath -> m Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> UnknownOption
UnknownOption.UnknownOption) [FilePath]
us
  (FilePath -> m Any) -> [FilePath] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (InvalidOption -> m Any
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (InvalidOption -> m Any)
-> (FilePath -> InvalidOption) -> FilePath -> m Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> InvalidOption
InvalidOption.InvalidOption) [FilePath]
is
  Config
c <- [Flag] -> m Config
forall (t :: * -> *) (m :: * -> *).
(Foldable t, MonadThrow m) =>
t Flag -> m Config
Config.fromFlags [Flag]
fs
  case [FilePath]
as of
    [] -> MissingArgument -> m Context
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (MissingArgument -> m Context) -> MissingArgument -> m Context
forall a b. (a -> b) -> a -> b
$ FilePath -> MissingArgument
MissingArgument.MissingArgument FilePath
"SOURCE"
    [FilePath
_] -> MissingArgument -> m Context
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (MissingArgument -> m Context) -> MissingArgument -> m Context
forall a b. (a -> b) -> a -> b
$ FilePath -> MissingArgument
MissingArgument.MissingArgument FilePath
"INPUT"
    [FilePath
_, FilePath
_] -> MissingArgument -> m Context
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (MissingArgument -> m Context) -> MissingArgument -> m Context
forall a b. (a -> b) -> a -> b
$ FilePath -> MissingArgument
MissingArgument.MissingArgument FilePath
"OUTPUT"
    FilePath
s : FilePath
i : FilePath
o : [FilePath]
xs -> do
      (FilePath -> m Any) -> [FilePath] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (ExtraArgument -> m Any
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (ExtraArgument -> m Any)
-> (FilePath -> ExtraArgument) -> FilePath -> m Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> ExtraArgument
ExtraArgument.ExtraArgument) [FilePath]
xs
      Context -> m Context
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Context {config :: Config
config = Config
c, input :: FilePath
input = FilePath
i, output :: FilePath
output = FilePath
o, source :: FilePath
source = FilePath
s}