--------------------------------------------------------------------
-- |
-- Module      : System.Cron.Internal.Describe.Optons
-- Description : Functions for constructing the options that control how
--               cron schedules are described
-- Copyright   : (c) Joseph Canero 2016
-- License     : MIT
--
-- Maintainer: Joseph Canero <jmc41493@gmail.com>
-- Portability: portable
--------------------------------------------------------------------
module System.Cron.Internal.Describe.Options where

-------------------------------------------------------------------------------
import Data.Default.Class
import Data.Semigroup as Semigroup
-------------------------------------------------------------------------------
import System.Cron.Internal.Describe.Types
-------------------------------------------------------------------------------


-- | Type that holds onto information for constructing options for
-- 'System.Cron.Describe.describe'.
data OptionBuilder = Builder (Options -> Options)


-- | Return a builder that creates the default options for
-- 'System.Cron.Describe.describe'. The default options are:
-- 'System.Cron.Describe.notVerbose' and 'System.Cron.Describe.twelveHourFormat'.
defaultOpts :: OptionBuilder
defaultOpts :: OptionBuilder
defaultOpts = (Options -> Options) -> OptionBuilder
Builder (Options -> Options -> Options
forall a b. a -> b -> a
const Options
forall a. Default a => a
def)


-- | Return a builder that sets the options to use a 24-hour time format.
-- This changes how hours are described. Using the 24-hour format,
-- all hours are returned as their left-padded numeric value (01:00, 22:00, etc)
twentyFourHourFormat :: OptionBuilder
twentyFourHourFormat :: OptionBuilder
twentyFourHourFormat = (Options -> Options) -> OptionBuilder
Builder (\Options
o -> Options
o {timeFormat = Hour24} )


-- | Return a builder that sets the options to use a 12-hour time format.
-- This changes how hours are described. Using the 12-hour format,
-- all hours are returned as their left-padded numeric value with their period
-- (01:00 AM, 10:00 PM, etc)
twelveHourFormat :: OptionBuilder
twelveHourFormat :: OptionBuilder
twelveHourFormat = (Options -> Options) -> OptionBuilder
Builder (\Options
o -> Options
o {timeFormat = Hour12} )


-- | Return a builder that sets the options to be verbose. A verbose description
-- doesn't eliminate unnecessary information. The only caveat being that month
-- information is only ever displayed if it isn't "*".
verbose :: OptionBuilder
verbose :: OptionBuilder
verbose = (Options -> Options) -> OptionBuilder
Builder (\Options
o -> Options
o {verbosity = Verbose})


-- | Return a builder that sets the options to not be verbose. All information
-- about the described cron schedule is returned. The only caveat being that
-- month information is only ever displayed if it isn't "*".
notVerbose :: OptionBuilder
notVerbose :: OptionBuilder
notVerbose = (Options -> Options) -> OptionBuilder
Builder (\Options
o -> Options
o {verbosity = NotVerbose})


-------------------------------------------------------------------------------
-- Internals
-------------------------------------------------------------------------------


getOpts :: OptionBuilder -> Options
getOpts :: OptionBuilder -> Options
getOpts (Builder Options -> Options
f) = Options -> Options
f Options
forall a. Default a => a
def


data Options = Opts {
    Options -> TimeFormat
timeFormat    :: TimeFormat
  , Options -> Verbosity
verbosity     :: Verbosity
  }

instance Default Options where
  def :: Options
def = Opts {timeFormat :: TimeFormat
timeFormat = TimeFormat
Hour12, verbosity :: Verbosity
verbosity = Verbosity
NotVerbose}

instance Semigroup.Semigroup OptionBuilder where
  (Builder Options -> Options
f) <> :: OptionBuilder -> OptionBuilder -> OptionBuilder
<> (Builder Options -> Options
a) = (Options -> Options) -> OptionBuilder
Builder (Options -> Options
a (Options -> Options) -> (Options -> Options) -> Options -> Options
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> Options
f)

instance Monoid OptionBuilder where
  mempty :: OptionBuilder
mempty = (Options -> Options) -> OptionBuilder
Builder (Options -> Options -> Options
forall a b. a -> b -> a
const Options
forall a. Default a => a
def)
  mappend :: OptionBuilder -> OptionBuilder -> OptionBuilder
mappend = OptionBuilder -> OptionBuilder -> OptionBuilder
forall a. Semigroup a => a -> a -> a
(<>)