{-# LANGUAGE Rank2Types #-}

module Cardano.Shell.Types
    ( CardanoFeature (..)
    , CardanoFeatureInit (..)
    , NoDependency (..)
    , ApplicationEnvironment (..)
    , CardanoApplication (..)
    , applicationProductionMode
    ) where

import           Cardano.Prelude

import           Control.Concurrent.Classy (MonadConc)

-- | The top level module we use to run the key functions.
newtype CardanoApplication = CardanoApplication { CardanoApplication -> IO ()
runCardanoApplication :: IO () }

-- | The application environment.
data ApplicationEnvironment
    = Development
    | Production
    deriving (ApplicationEnvironment -> ApplicationEnvironment -> Bool
(ApplicationEnvironment -> ApplicationEnvironment -> Bool)
-> (ApplicationEnvironment -> ApplicationEnvironment -> Bool)
-> Eq ApplicationEnvironment
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ApplicationEnvironment -> ApplicationEnvironment -> Bool
$c/= :: ApplicationEnvironment -> ApplicationEnvironment -> Bool
== :: ApplicationEnvironment -> ApplicationEnvironment -> Bool
$c== :: ApplicationEnvironment -> ApplicationEnvironment -> Bool
Eq, Int -> ApplicationEnvironment -> ShowS
[ApplicationEnvironment] -> ShowS
ApplicationEnvironment -> String
(Int -> ApplicationEnvironment -> ShowS)
-> (ApplicationEnvironment -> String)
-> ([ApplicationEnvironment] -> ShowS)
-> Show ApplicationEnvironment
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ApplicationEnvironment] -> ShowS
$cshowList :: [ApplicationEnvironment] -> ShowS
show :: ApplicationEnvironment -> String
$cshow :: ApplicationEnvironment -> String
showsPrec :: Int -> ApplicationEnvironment -> ShowS
$cshowsPrec :: Int -> ApplicationEnvironment -> ShowS
Show)

-- | A simple function to inform us.
applicationProductionMode :: ApplicationEnvironment -> Bool
applicationProductionMode :: ApplicationEnvironment -> Bool
applicationProductionMode ApplicationEnvironment
Production = Bool
True
applicationProductionMode ApplicationEnvironment
_          = Bool
False

-- | The option to not have any additional dependency for the @CardanoFeature@.
data NoDependency = NoDependency
    deriving (NoDependency -> NoDependency -> Bool
(NoDependency -> NoDependency -> Bool)
-> (NoDependency -> NoDependency -> Bool) -> Eq NoDependency
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NoDependency -> NoDependency -> Bool
$c/= :: NoDependency -> NoDependency -> Bool
== :: NoDependency -> NoDependency -> Bool
$c== :: NoDependency -> NoDependency -> Bool
Eq, Int -> NoDependency -> ShowS
[NoDependency] -> ShowS
NoDependency -> String
(Int -> NoDependency -> ShowS)
-> (NoDependency -> String)
-> ([NoDependency] -> ShowS)
-> Show NoDependency
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NoDependency] -> ShowS
$cshowList :: [NoDependency] -> ShowS
show :: NoDependency -> String
$cshow :: NoDependency -> String
showsPrec :: Int -> NoDependency -> ShowS
$cshowsPrec :: Int -> NoDependency -> ShowS
Show)

-- | The option to not have any additional configuration for the @CardanoFeature@.
data NoConfiguration = NoConfiguration
    deriving (NoConfiguration -> NoConfiguration -> Bool
(NoConfiguration -> NoConfiguration -> Bool)
-> (NoConfiguration -> NoConfiguration -> Bool)
-> Eq NoConfiguration
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NoConfiguration -> NoConfiguration -> Bool
$c/= :: NoConfiguration -> NoConfiguration -> Bool
== :: NoConfiguration -> NoConfiguration -> Bool
$c== :: NoConfiguration -> NoConfiguration -> Bool
Eq, Int -> NoConfiguration -> ShowS
[NoConfiguration] -> ShowS
NoConfiguration -> String
(Int -> NoConfiguration -> ShowS)
-> (NoConfiguration -> String)
-> ([NoConfiguration] -> ShowS)
-> Show NoConfiguration
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NoConfiguration] -> ShowS
$cshowList :: [NoConfiguration] -> ShowS
show :: NoConfiguration -> String
$cshow :: NoConfiguration -> String
showsPrec :: Int -> NoConfiguration -> ShowS
$cshowsPrec :: Int -> NoConfiguration -> ShowS
Show)

-- | Cardano feature initialization.
-- We are saying "you have the responsibility to make sure you use the right context!".
data CardanoFeatureInit env dependency cardanoConfiguration featureConfiguration layer = CardanoFeatureInit
    { CardanoFeatureInit
  env dependency cardanoConfiguration featureConfiguration layer
-> Text
featureType                   :: !Text
    -- ^ The type of the feature that we use.
    , CardanoFeatureInit
  env dependency cardanoConfiguration featureConfiguration layer
-> env
-> dependency
-> cardanoConfiguration
-> featureConfiguration
-> IO layer
featureInit                   :: env -> dependency -> cardanoConfiguration -> featureConfiguration -> IO layer
    -- ^ Again, we are not sure how is the user going to run the actual feature,
    -- so we provide him with the most flexible/powerful context we have, @IO@.
    -- Notice the arrangement of the parameters - specific, general, specific, general, result.
    , CardanoFeatureInit
  env dependency cardanoConfiguration featureConfiguration layer
-> layer -> IO ()
featureCleanup                :: layer -> IO ()
    -- ^ If the user wants to clean up the resources after the module has completed running,
    -- there is an option to do so.
    }

-- | The interface for the running feature, the high-level interface we use for running it.
data CardanoFeature = CardanoFeature
    { CardanoFeature -> Text
featureName     :: Text
    -- ^ The name of the feature.
    , CardanoFeature
-> forall (m :: * -> *). (MonadIO m, MonadConc m) => m ()
featureStart    :: forall m. (MonadIO m, MonadConc m) => m ()
    -- ^ What we call when we start the feature.
    , CardanoFeature
-> forall (m :: * -> *). (MonadIO m, MonadConc m) => m ()
featureShutdown :: forall m. (MonadIO m, MonadConc m) => m ()
    -- ^ What we call when we shut down the feature.
    }