{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}

-- | Default and active values for options
--   They can be defined and / or overridden separately from the
--   option definition themselves
module Data.Registry.Options.DefaultValues where

import Data.Dynamic
import Data.Registry
import Protolude

-- | Contain an optional value to return when an option is missing
newtype DefaultValue (s :: Symbol) a = DefaultValue (Maybe Dynamic)

-- | Contain an optional value to return when an option is present
newtype ActiveValue (s :: Symbol) a = ActiveValue (Maybe Dynamic)

-- | Get the default value in DefaultValue if it exists and has the right type
getDefaultValue :: forall (a :: Type) s. (Typeable a, KnownSymbol s) => DefaultValue s a -> Maybe a
getDefaultValue :: forall a (s :: Symbol).
(Typeable a, KnownSymbol s) =>
DefaultValue s a -> Maybe a
getDefaultValue (DefaultValue Maybe Dynamic
Nothing) = forall a. Maybe a
Nothing
getDefaultValue (DefaultValue (Just Dynamic
v)) = forall a. Typeable a => Dynamic -> Maybe a
fromDynamic Dynamic
v

-- | Get the active value in ActiveValue if it exists and has the right type
getActiveValue :: forall (a :: Type) s. (Typeable a, KnownSymbol s) => ActiveValue s a -> Maybe a
getActiveValue :: forall a (s :: Symbol).
(Typeable a, KnownSymbol s) =>
ActiveValue s a -> Maybe a
getActiveValue (ActiveValue Maybe Dynamic
Nothing) = forall a. Maybe a
Nothing
getActiveValue (ActiveValue (Just Dynamic
v)) = forall a. Typeable a => Dynamic -> Maybe a
fromDynamic Dynamic
v

-- | Allow to specify that a given field name and type has no default value
noDefaultValue :: forall s (a :: Type). (KnownSymbol s, Typeable a) => Typed (DefaultValue s a)
noDefaultValue :: forall (s :: Symbol) a.
(KnownSymbol s, Typeable a) =>
Typed (DefaultValue s a)
noDefaultValue = forall a. Typeable a => a -> Typed a
fun @(DefaultValue s a) (forall {k} (s :: Symbol) (a :: k).
Maybe Dynamic -> DefaultValue s a
DefaultValue forall a. Maybe a
Nothing)

-- | Allow to specify that a given field name and type has no active value
noActiveValue :: forall s (a :: Type). (KnownSymbol s, Typeable a) => Typed (ActiveValue s a)
noActiveValue :: forall (s :: Symbol) a.
(KnownSymbol s, Typeable a) =>
Typed (ActiveValue s a)
noActiveValue = forall a. Typeable a => a -> Typed a
fun (forall {k} (s :: Symbol) (a :: k). Maybe Dynamic -> ActiveValue s a
ActiveValue forall a. Maybe a
Nothing)

-- | Add a default value for a given field name and type
createDefaultValue :: forall s (a :: Type). (Typeable a, KnownSymbol s) => a -> DefaultValue s a
createDefaultValue :: forall (s :: Symbol) a.
(Typeable a, KnownSymbol s) =>
a -> DefaultValue s a
createDefaultValue = forall {k} (s :: Symbol) (a :: k).
Maybe Dynamic -> DefaultValue s a
DefaultValue forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Typeable a => a -> Dynamic
toDyn

-- | Add a default value for a given field name and type
createActiveValue :: forall s (a :: Type). (Typeable a, KnownSymbol s) => a -> ActiveValue s a
createActiveValue :: forall (s :: Symbol) a.
(Typeable a, KnownSymbol s) =>
a -> ActiveValue s a
createActiveValue = forall {k} (s :: Symbol) (a :: k). Maybe Dynamic -> ActiveValue s a
ActiveValue forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Typeable a => a -> Dynamic
toDyn