{-# LANGUAGE UnicodeSyntax #-}

module Todos.Main
  (module Todos.Default,
   module Todos.Config,
   module Todos.Dot,
   todos
  ) where

import Prelude hiding (putStrLn,readFile,getContents,print)
import Prelude.Unicode
import System.IO
import Data.Tree
import System.Exit

import System.Environment
import Config.Dyre

import Todos.Types
import Todos.Dates
import Todos.Dot
import Todos.Tree
import Todos.ReadConfig
import Todos.Loader
import Todos.Config
import Todos.Default

-- | Sort command line arguments:
-- (should we read other configs, command-line specified config files, command-line options)
sortCmdLine โˆท [String] โ†’ (๐”น, [String], [String])
sortCmdLine args = foldr sortOne (True, [],[]) args
  where
    sortOne "@@"           (_, configs, as) = (False, configs, as)
    sortOne ('@':'@':path) (_, configs, as) = (False, path:configs, as)
    sortOne ('@':path)     (r, configs, as) = (r, path:configs, as)
    sortOne option         (r, configs, as) = (r, configs, option:as)

-- | Real main funciton. Is called by dyre.
realTodos โˆท (RuntimeConfig c) โ‡’ TodosConfig c โ†’ IO ()
realTodos tcfg = do
  currDate โ† getCurrentDateTime 
  args โ† getArgs
  let (readOther, configs, args') = sortCmdLine args
  config โ† if readOther
             then readAllConfigs
             else return []
  -- Read options from command-line specified config files
  cmdLineConfig โ† concat `fmap` mapM readConfigFile configs
  let pres = (parseCommandLine tcfg) currDate (nullConfig tcfg) (config โงบ cmdLineConfig โงบ args')
  case pres of
    Parsed q files' โ†’ do
      let bc = toBaseConfig q
      files โ† glob files'
      todos โ† loadTodo bc currDate files
      let queried  = (filterTodos tcfg) currDate q todos
      case commandToRun bc of
        JustShow  โ†’ printTodos tcfg (mkPrintConfig currDate q tcfg) queried
        ShowAsDot โ†’ 
             putStrLn $ showAsDot (itemColor tcfg) (itemShape tcfg) queried
        SystemCommand cmd โ†’ do
             forT selected (spawn cmd)
             return ()
          where selected | outOnlyFirst bc = [Node (rootLabel $ head queried) []]
                         | otherwise       = queried

    ParseError str โ†’ error str
    CmdLineHelp โ†’ do putStrLn usage
                     exitWith ExitSuccess

-- | Main function to run. User can specify TodosConfig with any runtime config
-- type. By default (in todos.hs) defaultConfig is used, which uses DefaultConfig type.
todos โˆท (RuntimeConfig c) โ‡’ TodosConfig c โ†’ IO ()
todos = wrapMain $ defaultParams {
    projectName = "todos",
    realMain    = realTodos,
    statusOut   = const (return ())
    }