-- | Make a logger's output constant width by padding with the given string,
-- /even if the logger is/ @X (Nothing)@ /or/ @X (Just \"\")@. Useful to
-- reduce visual noise as a title logger shrinks and grows, to use a fixed
-- width for a logger that sometimes becomes Nothing, or even to create
-- fancy spacers or character based art effects.
--
-- It fills missing logger output with a repeated character like \".\",
-- \":\" or pattern, like \" -.-\". The cycling padding string is reversed on
-- the left of the logger output. This is mainly useful with AlignCenter.
fixedWidthL :: Align  -- ^ AlignCenter, AlignRight, or AlignLeft
            -> String -- ^ String to cycle to pad missing logger output
            -> Int    -- ^ Fixed length to output (including invisible formatting characters)
            -> Logger -> Logger
fixedWidthL a str n logger = do
    mbl <- logger
    let l = fromMaybe "" mbl
    case a of
       AlignCenter -> toL (take n $ padhalf l ++ l ++ cs)
       AlignRight -> toL (reverse (take n $ reverse l ++ cs))
       _ -> toL (take n $ l ++ cs)
  where
    toL = return . Just
    cs  = cycle str
    padhalf x = reverse $ take ((n - length x) `div` 2) cs

-- | Create a \"spacer\" logger, e.g. @logSp 3 -- loggerizes \'   \'@.
-- For more complex \"spacers\", use 'fixedWidthL' with @return Nothing@.
fixedWidthL :: Align  -- ^ AlignCenter, AlignRight, or AlignLeft
            -> String -- ^ String to cycle to pad missing logger output
            -> Int    -- ^ Fixed length to output (including invisible formatting characters)
            -> Logger -> Logger
fixedWidthL a str n logger = do
    mbl <- logger
    let l = fromMaybe "" mbl
    case a of
       AlignCenter -> toL (take n $ padhalf l ++ l ++ cs)
       AlignRight -> toL (reverse (take n $ reverse l ++ cs))
       _ -> toL (take n $ l ++ cs)
  where
    toL = return . Just
    cs  = cycle str
    padhalf x = reverse $ take ((n - length x) `div` 2) cs

-- | Create a \"spacer\" logger, e.g. @logSp 3 -- loggerizes \'   \'@.
-- For more complex \"spacers\", use 'fixedWidthL' with @return Nothing@.
fixedWidthL a str n logger = do
    mbl <- logger
    let l = fromMaybe "" mbl
    case a of
       AlignCenter -> toL (take n $ padhalf l ++ l ++ cs)
       AlignRight -> toL (reverse (take n $ reverse l ++ cs))
       _ -> toL (take n $ l ++ cs)
  where
    toL = return . Just
    cs  = cycle str
    padhalf x = reverse $ take ((n - length x) `div` 2) cs

-- | Create a \"spacer\" logger, e.g. @logSp 3 -- loggerizes \'   \'@.
-- For more complex \"spacers\", use 'fixedWidthL' with @return Nothing@.