{-# LANGUAGE UndecidableInstances #-}

module Cfg.Deriving.SubConfig where

import Cfg.Deriving.LabelModifier (LabelModifier (..))
import Cfg.Options (ConfigOptions (..), defaultConfigOptions)
import Cfg.Source (NestedConfig (..))
import Cfg.Source.NestedConfig
import GHC.Generics (Generic (..))
import Cfg.Parser.ConfigParser
import Cfg.Parser
import Data.Coerce

newtype SubConfig a = SubConfig {forall a. SubConfig a -> a
unSubConfig :: a}

instance Generic a => Generic (SubConfig a) where
    type Rep (SubConfig a) = Rep a
    to :: forall x. Rep (SubConfig a) x -> SubConfig a
to = a -> SubConfig a
forall a. a -> SubConfig a
SubConfig (a -> SubConfig a) -> (Rep a x -> a) -> Rep a x -> SubConfig a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep a x -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to
    from :: forall x. SubConfig a -> Rep (SubConfig a) x
from (SubConfig a
x) = a -> Rep a x
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from a
x

newtype SubConfigOpts t a = SubConfigOpts {forall t a. SubConfigOpts t a -> a
unSubConfigOpts :: a}

instance Generic a => Generic (SubConfigOpts t a) where
    type Rep (SubConfigOpts t a) = Rep a
    to :: forall x. Rep (SubConfigOpts t a) x -> SubConfigOpts t a
to = a -> SubConfigOpts t a
forall t a. a -> SubConfigOpts t a
SubConfigOpts (a -> SubConfigOpts t a)
-> (Rep a x -> a) -> Rep a x -> SubConfigOpts t a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep a x -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to
    from :: forall x. SubConfigOpts t a -> Rep (SubConfigOpts t a) x
from (SubConfigOpts a
x) = a -> Rep a x
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from a
x

class GetConfigOptions t where
    getConfigOptions :: ConfigOptions

instance (LabelModifier t) => GetConfigOptions t where
    getConfigOptions :: ConfigOptions
getConfigOptions = (Text -> Text) -> ConfigOptions
ConfigOptions (forall t. LabelModifier t => Text -> Text
getLabelModifier @t)

-- Source
instance (Generic a, GConfigForest (Rep a)) => NestedConfig (SubConfig a) where
    toNestedConfig :: [Tree Text]
toNestedConfig = forall a.
(Generic a, GConfigForest (Rep a)) =>
ConfigOptions -> [Tree Text]
defaultToNestedConfig @a ConfigOptions
defaultConfigOptions

instance (GetConfigOptions t, Generic a, GConfigForest (Rep a)) => NestedConfig (SubConfigOpts t a) where
    toNestedConfig :: [Tree Text]
toNestedConfig = forall a.
(Generic a, GConfigForest (Rep a)) =>
ConfigOptions -> [Tree Text]
defaultToNestedConfig @a (forall t. GetConfigOptions t => ConfigOptions
getConfigOptions @t)

-- Parser
instance (Generic a, GNestedParser (Rep a)) => NestedParser (SubConfig a) where
  parseNestedConfig :: Tree Text -> Either ConfigParseError (SubConfig a)
parseNestedConfig Tree Text
tree = Either ConfigParseError a -> Either ConfigParseError (SubConfig a)
forall a b. Coercible a b => a -> b
coerce (Either ConfigParseError a
 -> Either ConfigParseError (SubConfig a))
-> (Either ConfigParseError a
    -> Either ConfigParseError (SubConfig a))
-> Either ConfigParseError a
-> Either ConfigParseError (SubConfig a)
forall a. a -> a -> a
`asTypeOf` (a -> SubConfig a)
-> Either ConfigParseError a
-> Either ConfigParseError (SubConfig a)
forall a b.
(a -> b) -> Either ConfigParseError a -> Either ConfigParseError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> SubConfig a
forall a. a -> SubConfig a
SubConfig (Either ConfigParseError a
 -> Either ConfigParseError (SubConfig a))
-> Either ConfigParseError a
-> Either ConfigParseError (SubConfig a)
forall a b. (a -> b) -> a -> b
$ ConfigOptions -> Tree Text -> Either ConfigParseError a
forall a.
(Generic a, GNestedParser (Rep a)) =>
ConfigOptions -> Tree Text -> Either ConfigParseError a
defaultParseNestedConfig ConfigOptions
defaultConfigOptions Tree Text
tree

instance (GetConfigOptions t, Generic a, GNestedParser (Rep a)) => NestedParser (SubConfigOpts t a) where
  parseNestedConfig :: Tree Text -> Either ConfigParseError (SubConfigOpts t a)
parseNestedConfig Tree Text
tree = Either ConfigParseError a
-> Either ConfigParseError (SubConfigOpts t a)
forall a b. Coercible a b => a -> b
coerce (Either ConfigParseError a
 -> Either ConfigParseError (SubConfigOpts t a))
-> (Either ConfigParseError a
    -> Either ConfigParseError (SubConfigOpts t a))
-> Either ConfigParseError a
-> Either ConfigParseError (SubConfigOpts t a)
forall a. a -> a -> a
`asTypeOf` (a -> SubConfigOpts t a)
-> Either ConfigParseError a
-> Either ConfigParseError (SubConfigOpts t a)
forall a b.
(a -> b) -> Either ConfigParseError a -> Either ConfigParseError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> SubConfigOpts t a
forall t a. a -> SubConfigOpts t a
SubConfigOpts (Either ConfigParseError a
 -> Either ConfigParseError (SubConfigOpts t a))
-> Either ConfigParseError a
-> Either ConfigParseError (SubConfigOpts t a)
forall a b. (a -> b) -> a -> b
$ ConfigOptions -> Tree Text -> Either ConfigParseError a
forall a.
(Generic a, GNestedParser (Rep a)) =>
ConfigOptions -> Tree Text -> Either ConfigParseError a
defaultParseNestedConfig (forall t. GetConfigOptions t => ConfigOptions
getConfigOptions @t) Tree Text
tree