module System.Console.ConfigFile
  (
    readFromFile
  ) where


import System.Console.Command
import System.Console.Internal

import           Control.Applicative    ((<$>))
import           Control.Exception      (tryJust)
import           Control.Monad          (guard)
import           Control.Monad.IO.Class (MonadIO,liftIO)
import           Data.List              (isPrefixOf,concat,break)
import qualified Data.List.Split as Split
import qualified Data.Map        as Map
import           Data.Map               (Map)
import           Data.Maybe             (isJust)
import qualified Data.Tree       as Tree
import           System.Directory       (getAppUserDataDirectory)
import           System.IO.Error        (isDoesNotExistError)


readFromFile :: (MonadIO m) => Commands m -> UserCommand -> m [Setting]
readFromFile commands command = liftIO $ do
  dataDir <- getAppUserDataDirectory $ name (Tree.rootLabel commands)
  let configFile = dataDir ++ "/" ++ "config"
  fileContents <- either (const "") id <$> tryJust (guard . isDoesNotExistError) (readFile configFile)
  return . map parseSetting $ relevantLines command fileContents

relevantLines :: UserCommand -> String -> [String]
relevantLines c = concat . map snd . filter (flip isPrefixOf c . fst) . map parseSection . s . lines
 where

  s :: [String] -> [[String]]
  s = Split.split . Split.keepDelimsL $ Split.whenElt (isJust . header)

  header :: String -> Maybe UserCommand
  header ('[' : xs) = Just . words . takeWhile (/= ']') $ xs
  header _          = Nothing

  parseSection :: [String] -> (UserCommand,[String])
  parseSection (h : rest) = case header h of
    Just c  -> (c,rest)
    Nothing -> ([],h : rest)
  parseSection []         = ([],[])

parseSetting :: String -> Setting
parseSetting s = let (i,v) = break (== '=') s in
  (
    Long i
  , case v of
      []         -> Nothing
      '=' : rest -> Just rest
  )