content: {-# LANGUAGE NoImplicitPrelude #-}
  
  module CLI.Commands
    ( GlobalOptions (..),
      App (..),
      Command (..),
      parseCLI,
    )
  where
  
  import Options.Applicative
    ( Parser,
      command,
      customExecParser,
      fullDesc,
      help,
      helper,
      info,
      long,
      metavar,
      prefs,
      progDesc,
      short,
      showHelpOnError,
      strArgument,
      subparser,
      switch,
    )
  import qualified Options.Applicative as OA
  import Relude hiding (ByteString)
  
  data Command
    = Build [FilePath]
    | Check [FilePath]
    | About
    deriving (Show)
  
  data App = App
    { operations :: Command,
      options :: GlobalOptions
    }
    deriving (Show)
  
  newtype GlobalOptions = GlobalOptions
    { version :: Bool
    }
    deriving (Show)
  
  commandParser :: Parser Command
  commandParser =
    buildOperation
      [ ("build", "builds Haskell code from GQL source", Build <$> readFiles),
        ("check", "check if built Haskell code represent GQL source", Check <$> readFiles),
        ("about", "api information", pure About)
      ]
  
  buildOperation :: [(String, String, Parser Command)] -> Parser Command
  buildOperation xs = joinParsers $ map parseOperation xs
  
  joinParsers :: [OA.Mod OA.CommandFields a] -> Parser a
  joinParsers xs = subparser $ mconcat xs
  
  parseOperation :: (String, String, Parser Command) -> OA.Mod OA.CommandFields Command
  parseOperation (bName, bDesc, bValue) =
    command bName (info (helper <*> bValue) (fullDesc <> progDesc bDesc))
  
  readFiles :: Parser [String]
  readFiles =
    (many . strArgument . mconcat)
      [ metavar "dir",
        help "source dirs with code-gen.yaml file for generating APIs"
      ]
  
  parseCLI :: IO App
  parseCLI =
    customExecParser
      (prefs showHelpOnError)
      (info (helper <*> parseApp) description)
  
  parseApp :: OA.Parser App
  parseApp = App <$> commandParser <*> parseOptions
  
  parseOptions :: Parser GlobalOptions
  parseOptions = GlobalOptions <$> switch (long "version" <> short 'v' <> help "show Version number")
  
  description :: OA.InfoMod a
  description = fullDesc <> progDesc "Morpheus GraphQL CLI - haskell Api Generator"
  