content: module Reanimate.Driver.CLI
    ( getDriverOptions
    , Options(..)
    , Command(..)
    , Preset(..)
    , Format(..)
    , Raster(..)
    , showFormat
    , showRaster
    ) where
  
  import           Data.Char           (toLower)
  import           Options.Applicative
  import           Prelude
  import           Reanimate.Render    (FPS, Format (..), Height, Raster (..), Width)
  
  newtype Options = Options
    { optsCommand :: Command
    } deriving (Show)
  
  data Command
    = Raw
      { rawOutputFolder :: FilePath
      , rawFrameOffset  :: Int
      , rawPrettyPrint  :: Bool
      }
    | Test
    | Check
    | View
      { viewDetach  :: Bool
      }
    | Render
      { renderTarget  :: Maybe String
      , renderFPS     :: Maybe FPS
      , renderWidth   :: Maybe Width
      , renderHeight  :: Maybe Height
      , renderCompile :: Bool
      , renderFormat  :: Maybe Format
      , renderPreset  :: Maybe Preset
      , renderRaster  :: Raster
      , renderPartial :: Bool
      , renderHash    :: Bool
      }
     deriving (Show)
  
  data Preset = Youtube | ExampleGif | Quick | MediumQ | HighQ | LowFPS
    deriving (Show)
  
  readRaster :: String -> Maybe Raster
  readRaster raster =
    case map toLower raster of
      "none"        -> Just RasterNone
      "auto"        -> Just RasterAuto
      "inkscape"    -> Just RasterInkscape
      "rsvg"        -> Just RasterRSvg
      "imagemagick" -> Just RasterMagick
      _             -> Nothing
  
  showRaster :: Raster -> String
  showRaster RasterNone     = "none"
  showRaster RasterAuto     = "auto"
  showRaster RasterInkscape = "inkscape"
  showRaster RasterRSvg     = "rsvg"
  showRaster RasterMagick   = "imagemagick"
  
  readFormat :: String -> Maybe Format
  readFormat fmt =
    case map toLower fmt of
      "mp4"  -> Just RenderMp4
      "gif"  -> Just RenderGif
      "webm" -> Just RenderWebm
      _      -> Nothing
  
  showFormat :: Format -> String
  showFormat RenderMp4  = "mp4"
  showFormat RenderGif  = "gif"
  showFormat RenderWebm = "webm"
  
  readPreset :: String -> Maybe Preset
  readPreset preset =
    case map toLower preset of
      "youtube" -> Just Youtube
      "gif"     -> Just ExampleGif
      "quick"   -> Just Quick
      "medium"  -> Just MediumQ
      "high"    -> Just HighQ
      "lowfps"  -> Just LowFPS
      _         -> Nothing
  
  showPreset :: Preset -> String
  showPreset Youtube    = "youtube"
  showPreset ExampleGif = "gif"
  showPreset Quick      = "quick"
  showPreset MediumQ    = "medium"
  showPreset HighQ      = "high"
  showPreset LowFPS     = "lowfps"
  
  options :: Parser Options
  options = Options <$> commandP
  
  commandP :: Parser Command
  commandP = subparser(
       command "test" testCommand
    <> commandGroup "Internal commands"
    <> internal )
    <|> hsubparser
      ( command "check" checkCommand
      <> command "view" viewCommand
      <> command "render" renderCommand
      <> command "raw" rawCommand
      )
    <|> infoParser viewCommand
  
  rawCommand :: ParserInfo Command
  rawCommand = info parse
      (progDesc "Output raw SVGs for animation at 60 fps. Used internally by viewer.")
    where
      parse = Raw
        <$> strOption
          ( long "output" <>
            short 'o' <>
            metavar "PATH" <>
            help "Output folder" <>
            value ".")
        <*> option auto
          ( long "offset" <>
            metavar "NUMBER" <>
            help "Frame offset" <>
            value 0)
        <*> switch
          ( long "pretty-print" <>
            short 'p' <>
            help "Pretty print svg")
  
  testCommand :: ParserInfo Command
  testCommand = info (parse <**> helper)
      (progDesc "Generate 10 frames spread out evenly across the animation. Used \
                \internally by the test-suite.")
    where
      parse = pure Test
  
  checkCommand :: ParserInfo Command
  checkCommand = info parse
      (progDesc "Run a system's diagnostic and report any missing external dependencies.")
    where
      parse = pure Check
  
  viewCommand :: ParserInfo Command
  viewCommand = info parse
      (progDesc "Play animation in browser window.")
    where
      parse = View
        <$> switch
          (long "detach" <> short 'd')
  
  renderCommand :: ParserInfo Command
  renderCommand = info parse
      (progDesc "Render animation to file.")
    where
      -- fromPreset :: (Maybe Preset -> (Command -> Command))
      -- fromPreset Nothing = id
      -- fromPreset (Just ExampleGif) = \cmd -> cmd{renderFPS=24}
      -- modParser :: Parser (Command -> Command)
      -- modParser = fmap fromPreset $
      --   optional (option (maybeReader readPreset)
      --       (long "preset" <> showDefaultWith showPreset
      --       <> metavar "TYPE"
      --       <> help "Parameter presets: youtube, gif, quick"))
      parse = Render
        <$> optional (strOption (long "target"
                      <> short 'o'
                      <> metavar "FILE"
                      <> help "Write output to FILE"))
        <*> optional (option auto
            (long "fps" <> metavar "FPS"
            <> help "Set frames per second."))
        <*> optional (option auto
            (long "width" <> short 'w' <> metavar "PIXELS"
            <> help "Set video width."))
        <*> optional (option auto
            (long "height" <> short 'h'
            <> metavar "PIXELS" <> help "Set video height."))
        <*> switch (long "compile"
                    <> help "Compile source code before rendering.")
        <*> optional (option (maybeReader readFormat)
            (long "format" <> metavar "FMT"
            <> help "Video format: mp4, gif, webm"))
        <*> optional (option (maybeReader readPreset)
            (long "preset" <> showDefaultWith showPreset
            <> metavar "TYPE"
            <> help "Parameter presets: youtube, gif, quick, medium, high"))
        <*> option (maybeReader readRaster)
            (long "raster" <> showDefaultWith showRaster
            <> metavar "RASTER"
            <> value RasterNone
            <> help "Raster engine: none, auto, inkscape, rsvg, imagemagick")
        <*> switch
          (long "partial"
          <> help "Produce partial animation even if frame generation was \
                  \interrupted by ctrl-c")
        <*> flag True False
          (long "disable-hashing"
          <> help "Disable SVG dedup via hashing. This might improve performance \
                  \if all your frames are unique.")
  
  opts :: ParserInfo Options
  opts = info (options <**> helper )
    ( fullDesc
    <> progDesc "This program contains an animation which can either be viewed \
                \in a web-browser or rendered to disk."
    )
  
  getDriverOptions :: IO Options
  getDriverOptions = customExecParser (prefs showHelpOnError) opts
  