-- Copyright 2014 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

-- | A wrapper around 'Ui.StateT' that provides logging.
module Ui.UiLog where
import qualified Control.Monad.Identity as Identity
import qualified Control.Monad.Trans as Trans

import qualified Util.Log as Log
import qualified Ui.Ui as Ui
import qualified Ui.Update as Update
import Global


type UiLogT m = Ui.StateT (Log.LogT m)
type UiLog = UiLogT Identity.Identity

run :: Monad m => Ui.State -> UiLogT m a
    -> m (Either Ui.Error (a, Ui.State, Update.UiDamage), [Log.Msg])
run :: forall (m :: * -> *) a.
Monad m =>
State -> UiLogT m a -> m (Either Error (a, State, UiDamage), [Msg])
run State
state = LogT m (Either Error (a, State, UiDamage))
-> m (Either Error (a, State, UiDamage), [Msg])
forall (m :: * -> *) a. Monad m => LogT m a -> m (a, [Msg])
Log.run (LogT m (Either Error (a, State, UiDamage))
 -> m (Either Error (a, State, UiDamage), [Msg]))
-> (UiLogT m a -> LogT m (Either Error (a, State, UiDamage)))
-> UiLogT m a
-> m (Either Error (a, State, UiDamage), [Msg])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> UiLogT m a -> LogT m (Either Error (a, State, UiDamage))
forall (m :: * -> *) a.
Monad m =>
State -> StateT m a -> m (Either Error (a, State, UiDamage))
Ui.run State
state

run_id :: Ui.State -> UiLog a
    -> (Either Ui.Error (a, Ui.State, Update.UiDamage), [Log.Msg])
run_id :: forall a.
State -> UiLog a -> (Either Error (a, State, UiDamage), [Msg])
run_id State
state = Identity (Either Error (a, State, UiDamage), [Msg])
-> (Either Error (a, State, UiDamage), [Msg])
forall a. Identity a -> a
Identity.runIdentity (Identity (Either Error (a, State, UiDamage), [Msg])
 -> (Either Error (a, State, UiDamage), [Msg]))
-> (UiLog a -> Identity (Either Error (a, State, UiDamage), [Msg]))
-> UiLog a
-> (Either Error (a, State, UiDamage), [Msg])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State
-> UiLog a -> Identity (Either Error (a, State, UiDamage), [Msg])
forall (m :: * -> *) a.
Monad m =>
State -> UiLogT m a -> m (Either Error (a, State, UiDamage), [Msg])
run State
state

exec_id :: Ui.State -> UiLog a
    -> (Either Ui.Error (Ui.State, Update.UiDamage), [Log.Msg])
exec_id :: forall a.
State -> UiLog a -> (Either Error (State, UiDamage), [Msg])
exec_id State
state = (Either Error (a, State, UiDamage)
 -> Either Error (State, UiDamage))
-> (Either Error (a, State, UiDamage), [Msg])
-> (Either Error (State, UiDamage), [Msg])
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (((a, State, UiDamage) -> (State, UiDamage))
-> Either Error (a, State, UiDamage)
-> Either Error (State, UiDamage)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, State, UiDamage) -> (State, UiDamage)
forall {a} {a} {b}. (a, a, b) -> (a, b)
extract) ((Either Error (a, State, UiDamage), [Msg])
 -> (Either Error (State, UiDamage), [Msg]))
-> (UiLog a -> (Either Error (a, State, UiDamage), [Msg]))
-> UiLog a
-> (Either Error (State, UiDamage), [Msg])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> UiLog a -> (Either Error (a, State, UiDamage), [Msg])
forall a.
State -> UiLog a -> (Either Error (a, State, UiDamage), [Msg])
run_id State
state
    where extract :: (a, a, b) -> (a, b)
extract (a
_, a
state, b
updates) = (a
state, b
updates)

instance Monad m => Log.LogMonad (UiLogT m) where
    write :: Msg -> UiLogT m ()
write = LogT m () -> UiLogT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
Trans.lift (LogT m () -> UiLogT m ())
-> (Msg -> LogT m ()) -> Msg -> UiLogT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Msg -> LogT m ()
forall (m :: * -> *). LogMonad m => Msg -> m ()
Log.write