{-# LANGUAGE LambdaCase #-}

module PMS.Infra.Watch.App.Control where

import System.IO
import qualified Control.Exception.Safe as E
import System.Log.FastLogger

import qualified PMS.Domain.Model.DM.Type as DM
import qualified PMS.Domain.Model.DS.Utility as DM

import PMS.Infra.Watch.DM.Type
import PMS.Infra.Watch.DM.Constant
import PMS.Infra.Watch.DS.Utility
import PMS.Infra.Watch.DS.Core

-- |
--
run :: DM.DomainContext ()
run :: DomainContext ()
run DomainData
domDat = do
  Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"[INFO] PMS.Infra.Watch.App.Control.run called."
  AppData
appDat <- IO AppData
defaultAppData
  AppData -> DomainContext ()
runWithAppData AppData
appDat DomainData
domDat

-- |
--
runWithAppData :: AppData -> DM.DomainContext ()
runWithAppData :: AppData -> DomainContext ()
runWithAppData AppData
appDat DomainData
domDat = do
  (TimedFastLogger, IO ())
logDat <- DomainData -> ErrorData -> IO (TimedFastLogger, IO ())
DM.createLogger DomainData
domDat ErrorData
_LOG_FILE_NAME
  (TimedFastLogger, IO ()) -> AppData -> DomainContext ()
runWithLogger (TimedFastLogger, IO ())
logDat AppData
appDat DomainData
domDat

-- |
--
runWithLogger :: (TimedFastLogger, IO ()) -> AppData -> DM.DomainContext ()
runWithLogger :: (TimedFastLogger, IO ()) -> AppData -> DomainContext ()
runWithLogger (TimedFastLogger
logger, IO ()
finalizeLogger) AppData
appDat DomainData
domDat = 
  (IO () -> (SomeException -> IO ()) -> IO ())
-> (SomeException -> IO ()) -> IO () -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip IO () -> (SomeException -> IO ()) -> IO ()
forall (m :: * -> *) a.
(HasCallStack, MonadCatch m) =>
m a -> (SomeException -> m a) -> m a
E.catchAny SomeException -> IO ()
forall {e} {b}. Exception e => e -> IO b
exception
    (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ (IO () -> IO () -> IO ()) -> IO () -> IO () -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip IO () -> IO () -> IO ()
forall (m :: * -> *) a b.
(HasCallStack, MonadMask m) =>
m a -> m b -> m a
E.finally IO ()
finalize
    (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ DomainData
-> AppData
-> TimedFastLogger
-> AppContext ()
-> IO (Either ErrorData ())
forall a.
DomainData
-> AppData
-> TimedFastLogger
-> AppContext a
-> IO (Either ErrorData a)
runApp DomainData
domDat AppData
appDat TimedFastLogger
logger AppContext ()
app
    IO (Either ErrorData ()) -> (Either ErrorData () -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Right ()
x -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
x
      Left  ErrorData
e -> ErrorData -> IO ()
forall {a}. Show a => a -> IO ()
errorEnd ErrorData
e

  where
    finalize :: IO ()
finalize = do
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"-----------------------------------------------------------------------------"
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"[INFO] PMS.Infra.Watch.App.Control.run finalize called."
      IO ()
finalizeLogger
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"-----------------------------------------------------------------------------"

    exception :: e -> IO b
exception e
e = do
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"-----------------------------------------------------------------------------"
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"[ERROR] PMS.Infra.Watch.App.Control.run exception occurred."
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr (ErrorData -> IO ()) -> ErrorData -> IO ()
forall a b. (a -> b) -> a -> b
$ e -> ErrorData
forall a. Show a => a -> ErrorData
show e
e
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"-----------------------------------------------------------------------------"
      e -> IO b
forall (m :: * -> *) e a.
(HasCallStack, MonadThrow m, Exception e) =>
e -> m a
E.throwIO e
e

    errorEnd :: a -> IO ()
errorEnd a
e = do
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"-----------------------------------------------------------------------------"
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"[ERROR] PMS.Infra.Watch.App.Control.run end with error."
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr (ErrorData -> IO ()) -> ErrorData -> IO ()
forall a b. (a -> b) -> a -> b
$ a -> ErrorData
forall a. Show a => a -> ErrorData
show a
e
      Handle -> ErrorData -> IO ()
hPutStrLn Handle
stderr ErrorData
"-----------------------------------------------------------------------------"