{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}

-- | This module provides the core 'Env' type for Navi.
module Navi.Env.Core
  ( -- * HasX-style Typeclasses
    HasEvents (..),
    HasLogEnv (..),
    HasLogQueue (..),
    HasNoteQueue (..),

    -- * Concrete Env
    Env (..),
  )
where

import Navi.Data.NaviLog (LogEnv)
import Navi.Data.NaviNote (NaviNote)
import Navi.Event.Types (AnyEvent)
import Navi.Prelude

-- | Retrieves the events.
class HasEvents env where
  getEvents :: env -> NonEmpty AnyEvent

-- | Retrieves the log environment.
class HasLogEnv env where
  getLogEnv :: env -> LogEnv
  localLogEnv :: (LogEnv -> LogEnv) -> env -> env

-- | Retrieves the log queue.
class HasLogQueue env where
  getLogQueue :: env -> TBQueue LogStr

-- | Retrieves the note queue.
class HasNoteQueue env where
  getNoteQueue :: env -> TBQueue NaviNote

-- | 'Env' holds all of our environment data that is used while running navi.
data Env = MkEnv
  { Env -> NonEmpty AnyEvent
events :: !(NonEmpty AnyEvent),
    Env -> LogEnv
logEnv :: !LogEnv,
    Env -> TBQueue LogStr
logQueue :: !(TBQueue LogStr),
    Env -> TBQueue NaviNote
noteQueue :: !(TBQueue NaviNote)
  }

makeFieldLabelsNoPrefix ''Env

instance HasEvents Env where
  getEvents :: Env -> NonEmpty AnyEvent
getEvents = forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (a :: OpticKind).
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall (a :: OpticKind). IsLabel "events" a => a
#events
  {-# INLINEABLE getEvents #-}

instance HasLogEnv Env where
  getLogEnv :: Env -> LogEnv
getLogEnv = forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (a :: OpticKind).
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall (a :: OpticKind). IsLabel "logEnv" a => a
#logEnv
  {-# INLINEABLE getLogEnv #-}
  localLogEnv :: (LogEnv -> LogEnv) -> Env -> Env
localLogEnv = forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (t :: OpticKind) (a :: OpticKind) (b :: OpticKind).
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over' forall (a :: OpticKind). IsLabel "logEnv" a => a
#logEnv
  {-# INLINEABLE localLogEnv #-}

instance HasLogQueue Env where
  getLogQueue :: Env -> TBQueue LogStr
getLogQueue = forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (a :: OpticKind).
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall (a :: OpticKind). IsLabel "logQueue" a => a
#logQueue
  {-# INLINEABLE getLogQueue #-}

instance HasNoteQueue Env where
  getNoteQueue :: Env -> TBQueue NaviNote
getNoteQueue = forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (a :: OpticKind).
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall (a :: OpticKind). IsLabel "noteQueue" a => a
#noteQueue
  {-# INLINEABLE getNoteQueue #-}