{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
# LANGUAGE GADTs                #
{-# LANGUAGE PatternSynonyms     #-}
# LANGUAGE ScopedTypeVariables #
{-# LANGUAGE TypeOperators       #-}
# OPTIONS_GHC -Wall #
# OPTIONS_GHC -Wno - unticked - promoted - constructors #

module System.TaskPipeline.Options
  ( -- * API
    getOptions
  , getOption
  , optionsVirtualFile
  , optionVirtualFile
  -- * Re-exports from docrecords
  , DocRec, Rec(..), (^^.), (^^?), (^^?!), (=:)
  , PathWithType(..)
  , docField
  , pattern FV
  ) where

import           Data.Aeson
import           Data.DocRecord
import           Data.DocRecord.OptParse
import           Data.Locations.SerializationMethod
import           Data.Locations.VirtualFile
import           Data.Typeable
import           GHC.TypeLits                          (KnownSymbol)
import           System.TaskPipeline.PTask
import           System.TaskPipeline.VirtualFileAccess

import           Prelude                               hiding (id, (.))


-- | Field Value. Allows you to directly pattern match on the output of
  ' getOptions'/'loadData '
pattern FV :: a -> DocField (s:|:a)
pattern FV v <- DocField _ (Right (Field v))

  | Creates a ' VirtualFile ' from a default set of options ( as a DocRec ) . To be
-- used with 'loadData'.
optionsVirtualFile
  :: forall rs. (Typeable rs, RecordUsableWithCLI rs)
  ^ The path for the options in the LocationTree
  ^ The DocRec containing the fields with their
                             -- docs and default values
  -> BidirVirtualFile (DocRec rs)
optionsVirtualFile path defOpts =
  withEmbeddedValue defOpts $
    bidirVirtualFile path $
         someBidirSerial (OptionsSerial id id :: OptionsSerial (DocRec rs))
      <> someBidirSerial YAMLSerial

-- | Just like 'optionsVirtualFile', but for a single field
optionVirtualFile
  :: (KnownSymbol s, Typeable t, ToJSON t, FieldFromCLI ('[s] :|: t))
  ^ The path for the option field in the LocationTree
  -> DocField ('[s] :|: t)  -- ^ The field, usually with default value (created
  with '  ' )
  -> BidirVirtualFile t
optionVirtualFile path field =
  dimap (field =:) (^^?! field) $
    optionsVirtualFile path (field :& RNil)

  | Add a set of options ( as a DocRec ) to the '  ' , in order to
-- expose them to the user, and returns the final values of these options
getOptions
  :: (LogThrow m, Typeable rs, RecordUsableWithCLI rs)
  ^ The path for the options in the LocationTree
  ^ The DocRec containing the fields with their
                             -- docs and default values
  ^ A PTask that returns the new options values ,
                             -- overriden by the user
getOptions path = loadData . optionsVirtualFile path

  | Just like '  ' , but for a single field .
getOption
  :: (LogThrow m, KnownSymbol s, Typeable t, ToJSON t, FieldFromCLI ('[s] :|: t))
  ^ The path for the option field in the LocationTree
  ^ The field ( created with '  ' )
  ^ A PTask that returns the new option ,
                             -- overriden by the user
getOption path = loadData . optionVirtualFile path

# LANGUAGE DataKinds           #
# LANGUAGE FlexibleContexts    #
# LANGUAGE PatternSynonyms     #
# LANGUAGE TypeOperators       #
 * API
 * Re-exports from docrecords
 | Field Value. Allows you to directly pattern match on the output of
 used with 'loadData'.
 docs and default values
 | Just like 'optionsVirtualFile', but for a single field
 ^ The field, usually with default value (created
 expose them to the user, and returns the final values of these options
 docs and default values
 overriden by the user
 overriden by the user
# LANGUAGE GADTs                #
# LANGUAGE ScopedTypeVariables #
# OPTIONS_GHC -Wall #
# OPTIONS_GHC -Wno - unticked - promoted - constructors #

module System.TaskPipeline.Options
    getOptions
  , getOption
  , optionsVirtualFile
  , optionVirtualFile
  , DocRec, Rec(..), (^^.), (^^?), (^^?!), (=:)
  , PathWithType(..)
  , docField
  , pattern FV
  ) where

import           Data.Aeson
import           Data.DocRecord
import           Data.DocRecord.OptParse
import           Data.Locations.SerializationMethod
import           Data.Locations.VirtualFile
import           Data.Typeable
import           GHC.TypeLits                          (KnownSymbol)
import           System.TaskPipeline.PTask
import           System.TaskPipeline.VirtualFileAccess

import           Prelude                               hiding (id, (.))


  ' getOptions'/'loadData '
pattern FV :: a -> DocField (s:|:a)
pattern FV v <- DocField _ (Right (Field v))

  | Creates a ' VirtualFile ' from a default set of options ( as a DocRec ) . To be
optionsVirtualFile
  :: forall rs. (Typeable rs, RecordUsableWithCLI rs)
  ^ The path for the options in the LocationTree
  ^ The DocRec containing the fields with their
  -> BidirVirtualFile (DocRec rs)
optionsVirtualFile path defOpts =
  withEmbeddedValue defOpts $
    bidirVirtualFile path $
         someBidirSerial (OptionsSerial id id :: OptionsSerial (DocRec rs))
      <> someBidirSerial YAMLSerial

optionVirtualFile
  :: (KnownSymbol s, Typeable t, ToJSON t, FieldFromCLI ('[s] :|: t))
  ^ The path for the option field in the LocationTree
  with '  ' )
  -> BidirVirtualFile t
optionVirtualFile path field =
  dimap (field =:) (^^?! field) $
    optionsVirtualFile path (field :& RNil)

  | Add a set of options ( as a DocRec ) to the '  ' , in order to
getOptions
  :: (LogThrow m, Typeable rs, RecordUsableWithCLI rs)
  ^ The path for the options in the LocationTree
  ^ The DocRec containing the fields with their
  ^ A PTask that returns the new options values ,
getOptions path = loadData . optionsVirtualFile path

  | Just like '  ' , but for a single field .
getOption
  :: (LogThrow m, KnownSymbol s, Typeable t, ToJSON t, FieldFromCLI ('[s] :|: t))
  ^ The path for the option field in the LocationTree
  ^ The field ( created with '  ' )
  ^ A PTask that returns the new option ,
getOption path = loadData . optionVirtualFile path
