content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuasiQuotes #-}
  
  module Main where
  
  import Parsing ( parseStartYear )
  import Path ( reldir )
  
  import qualified Turtle hiding (switch)
  import Prelude hiding (putStrLn)
  
  import Options.Applicative
      ( auto,
        optional,
        Alternative(many, (<|>)),
        Parser,
        flag',
        help,
        long,
        metavar,
        option,
        short,
        str,
        switch )
  
  import Hledger.Flow.PathHelpers (TurtlePath)
  import Hledger.Flow.Common ( hledgerInfoFromPath )
  import Hledger.Flow.Internals (versionInfo, systemInfo)
  import Hledger.Flow.BaseDir ( determineBaseDir )
  import qualified Hledger.Flow.RuntimeOptions as RT
  import Hledger.Flow.Reports ( generateReports )
  import Hledger.Flow.Import.CSVImport ( importCSVs )
  
  import qualified Data.Text.IO as T
  
  data ImportParams = ImportParams { maybeImportBaseDir :: Maybe TurtlePath
                                   , importStartYear :: Maybe String
                                   , onlyNewFiles :: Bool
                                   } deriving (Show)
  
  data ReportParams = ReportParams { maybeReportBaseDir :: Maybe TurtlePath
                                   , asciiReports :: Bool
                                   } deriving (Show)
  
  data Command = Import ImportParams | Report ReportParams deriving (Show)
  
  data MainParams = MainParams { verbosity :: Int
                               , hledgerPathOpt :: Maybe TurtlePath
                               , showOpts :: Bool
                               , batchSize :: Maybe Int
                               , sequential :: Bool
                               } deriving (Show)
  data BaseCommand = Version | Command { mainParams :: MainParams, command :: Command } deriving (Show)
  
  main :: IO ()
  main = do
    cmd <- Turtle.options "An hledger workflow focusing on automated statement import and classification:\nhttps://github.com/apauley/hledger-flow#readme" baseCommandParser
    case cmd of
      Version -> do
        sysInfo <- systemInfo
        T.putStrLn $ versionInfo sysInfo 
      Command mainParams' (Import subParams) -> toRuntimeOptionsImport mainParams' subParams >>= importCSVs
      Command mainParams' (Report subParams) -> toRuntimeOptionsReport mainParams' subParams >>= generateReports
  
  defaultBatchSize :: Int
  defaultBatchSize = 20
  
  determineBatchSize :: MainParams -> IO Int
  determineBatchSize mainParams' =
    case (batchSize mainParams') of
      Nothing   -> return defaultBatchSize
      Just size -> return size
  
  toRuntimeOptionsImport :: MainParams -> ImportParams -> IO RT.RuntimeOptions
  toRuntimeOptionsImport mainParams' subParams' = do
    startYear <- parseStartYear $ importStartYear subParams'
    let maybeBD = maybeImportBaseDir subParams' :: Maybe TurtlePath
    (bd, runDir) <- determineBaseDir maybeBD
    hli <- hledgerInfoFromPath $ hledgerPathOpt mainParams'
    size <- determineBatchSize mainParams'
    sysInfo <- systemInfo
    return RT.RuntimeOptions { RT.baseDir = bd
                             , RT.importRunDir = runDir
                             , RT.importStartYear = startYear
                             , RT.onlyNewFiles = onlyNewFiles subParams'
                             , RT.hfVersion = versionInfo sysInfo
                             , RT.hledgerInfo = hli
                             , RT.sysInfo = sysInfo
                             , RT.verbose = verbosity mainParams' > 0
                             , RT.showOptions = showOpts mainParams'
                             , RT.sequential = sequential mainParams'
                             , RT.batchSize = size
                             , RT.prettyReports = True
                             }
  
  toRuntimeOptionsReport :: MainParams -> ReportParams -> IO RT.RuntimeOptions
  toRuntimeOptionsReport mainParams' subParams' = do
    let maybeBD = maybeReportBaseDir subParams' :: Maybe TurtlePath
    (bd, _) <- determineBaseDir maybeBD
    hli <- hledgerInfoFromPath $ hledgerPathOpt mainParams'
    size <- determineBatchSize mainParams'
    sysInfo <- systemInfo
    return RT.RuntimeOptions { RT.baseDir = bd
                             , RT.importRunDir = [reldir|.|]
                             , RT.importStartYear = Nothing
                             , RT.onlyNewFiles = False
                             , RT.hfVersion = versionInfo sysInfo
                             , RT.hledgerInfo = hli
                             , RT.sysInfo = sysInfo
                             , RT.verbose = verbosity mainParams' > 0
                             , RT.showOptions = showOpts mainParams'
                             , RT.sequential = sequential mainParams'
                             , RT.batchSize = size
                             , RT.prettyReports = not(asciiReports subParams')
                             }
  
  baseCommandParser :: Parser BaseCommand
  baseCommandParser = (Command <$> verboseParser <*> commandParser)
    <|> flag' Version (long "version" <> short 'V' <> help "Display version information")
  
  commandParser :: Parser Command
  commandParser = fmap Import (Turtle.subcommand "import" "Uses hledger with your own rules and/or scripts to convert electronic statements into categorised journal files" subcommandParserImport)
    <|> fmap Report (Turtle.subcommand "report" "Generate Reports" subcommandParserReport)
  
  verboseParser :: Parser MainParams
  verboseParser = MainParams
    <$> (length <$> many (flag' () (long "verbose" <> short 'v' <> help "Print more verbose output")))
    <*> optional (Turtle.optPath "hledger-path" 'H' "The full path to an hledger executable")
    <*> switch (long "show-options" <> help "Print the options this program will run with")
    <*> optional (option auto (long "batch-size" <> metavar "SIZE" <> help ("Parallel processing of files are done in batches of the specified size. Default: " <> show defaultBatchSize <> ". Ignored during sequential processing.")))
    <*> switch (long "sequential" <> help "Disable parallel processing")
  
  subcommandParserImport :: Parser ImportParams
  subcommandParserImport = ImportParams
    <$> optional (Turtle.argPath "dir" "The directory to import. Use the base directory for a full import or a sub-directory for a partial import. Defaults to the current directory.")
    <*> optional (option str (long "start-year" <> metavar "YEAR" <> help "Import only from the specified year and onwards, ignoring previous years. By default all available years are imported. Valid values include a 4-digit year or 'current' for the current year"))
    <*> switch (long "new-files-only" <> help "Don't regenerate transaction files if they are already present. This applies to hledger journal files as well as files produced by the preprocess and construct scripts.")
  
  subcommandParserReport :: Parser ReportParams
  subcommandParserReport = ReportParams
    <$> optional (Turtle.argPath "basedir" "The hledger-flow base directory")
    <*> switch (long "ascii-reports" <> help "If to avoid using hledger --pretty-tables flag when generating reports.")
  