content: {-# LANGUAGE NoImplicitPrelude #-}
  {-# LANGUAGE OverloadedStrings #-}
  
  module Brok.Parser.Options
      ( options
      ) where
  
  import ClassyPrelude
  
  import Data.Attoparsec.Text
  
  import Brok.Parser.Attoparsec
  import Brok.Parser.Links      (url)
  import Brok.Types.Config
  import Brok.Types.Next        (Next (..))
  
  data Option
      = Cache (Maybe Integer)
      | Interval Integer
      | Ignore [Text]
      | Files [Text]
      | NoColor
      | CheckCerts
      | OnlyFailures
  
  onlyFailuresP :: Parser Option
  onlyFailuresP = lexeme $ string "--only-failures" $> OnlyFailures
  
  noColorP :: Parser Option
  noColorP = lexeme $ string "--no-color" $> NoColor
  
  checkCertsP :: Parser Option
  checkCertsP = lexeme $ string "--check-certs" $> CheckCerts
  
  noCacheP :: Parser Option
  noCacheP = lexeme $ string "--no-cache" $> Cache Nothing
  
  cacheP :: Parser Option
  cacheP = lexeme $ Cache . Just <$> (string "--cache" *> char '\n' *> decimal)
  
  intervalP :: Parser Option
  intervalP = lexeme $ Interval <$> (string "--interval" *> char '\n' *> decimal)
  
  urlP :: Parser Text
  urlP = lexeme url
  
  ignoreP :: Parser Option
  ignoreP = lexeme $ Ignore <$> (string "--ignore" *> char '\n' *> many1 urlP)
  
  fileP :: Parser Text
  fileP = lexeme $ manyChars (notChar '\n')
  
  optsToConfig :: [Option] -> Config
  optsToConfig = foldl' convert defaultConfig
    where
      convert dc (Cache i)    = dc {cache = i}
      convert dc (Ignore i)   = dc {ignore = i}
      convert dc (Interval i) = dc {interval = i}
      convert dc (Files i)    = dc {files = i}
      convert dc NoColor      = dc {noColor = True}
      convert dc CheckCerts   = dc {checkCerts = True}
      convert dc OnlyFailures = dc {onlyFailures = True}
  
  arguments :: Parser Config
  arguments = do
      opts <-
          many'
              (noCacheP <|> cacheP <|> intervalP <|> ignoreP <|> noColorP <|> checkCertsP <|>
               onlyFailuresP)
      fls <- many1 fileP
      pure . optsToConfig $ opts <> [Files fls]
  
  helpP :: Parser Next
  helpP = lexeme $ (string "--help" <|> string "-h") $> Help
  
  versionP :: Parser Next
  versionP = lexeme $ (string "--version" <|> string "-v") $> Version
  
  next :: Parser Next
  next = helpP <|> versionP <|> (Continue <$> arguments)
  
  -- run parser
  options :: [Text] -> Either Text Next
  options []      = Left "No files provided"
  options content = first tshow $ parseOnly next (unlines content)
  