module Options where

import System.Console.GetOpt
import Data.Maybe(fromMaybe)

data LimitType = NumLimit Integer -- limit feed size to given number
               | NoLimit -- don't limit
               | KeepLimit -- limit feed size to current size (during add-item)
     deriving Show

data DescType = DescFile FilePath -- means -Dfoo
              | DescCLI String -- means -dFoo
              | DescSTDIN -- means --pipe-mode
     deriving Show

data Options = Options
 { optVerbose     :: Bool
 , optShowVersion :: Bool
 , optPreDesc     :: Bool
 , optOutput      :: Maybe FilePath
 , optInput       :: Maybe FilePath
 , optDescription :: DescType
 , optLimit       :: LimitType
 , optTitle       :: String
 , optLink        :: Maybe String
 } deriving Show

defaultOptions :: Options
defaultOptions    = Options
 { optVerbose     = False
 , optShowVersion = False
 , optPreDesc     = False
 , optOutput      = Nothing
 , optInput       = Nothing
 , optLimit       = NoLimit
 , optTitle       = ""
 , optDescription = DescCLI ""
 , optLink        = Nothing
 }

options :: [OptDescr (Options -> Options)]
options =
 [ Option ['v']     ["verbose"]
     (NoArg (\ opts -> opts { optVerbose = True }))
     "chatty output on stderr"
 , Option ['V','?'] ["version"]
     (NoArg (\ opts -> opts { optShowVersion = True }))
     "show version number"

 , Option ['p'] ["pre"]
     (NoArg (\ opts -> opts { optPreDesc = True }))
     "add <pre> tag to description for html readers"

 , Option [] ["pipe-mode"]
     (NoArg (\ opts -> opts { optDescription = DescSTDIN }))
     "description pipe mode, suitable for piping commands into, or -d or -D"

 , Option ['D']     ["description-file"]
     (ReqArg ((\ f opts -> opts { optDescription = DescFile f })) "FILE")
     "read the description from given file. or -d or --pipe-mode"

 , Option ['d']     ["description"]
         (ReqArg (\ t opts -> opts { optDescription = DescCLI t }) "description")
         "feed item description from command line. or -D or --pipe-mode"

 , Option ['o']     ["output"]
     (ReqArg ((\ f opts -> opts { optOutput = Just f })) "FILE")
     "output to this file, or -u"

 , Option ['u']     ["update-file"]
    (ReqArg ((\ f opts -> opts { optInput = Just f
                               , optOutput = Just f })) "FILE")
    "update-file FILE"
 , Option []     ["limit"]
    (OptArg ((\ m opts -> opts { optLimit = 
                                   case m of
                                     Nothing -> KeepLimit
                                     Just l  -> NumLimit (fromMaybe (error ("--limit= expecting number, got " ++ show l)) (readInteger l))
                               }))
            "NUM")
    "limit=NUM"
 , Option ['i']     ["input"]
     (ReqArg ((\ f opts -> opts { optInput = Just f })) "FILE")
     "input FILE"
 , Option ['l']     ["link"]
     (ReqArg ((\ f opts -> opts { optLink = Just f })) "URL")
     "link http://foo.com"
 , Option ['t']     ["title"]
         (ReqArg (\ t opts -> opts { optTitle = t }) "title")
         "feed item title"

 ]

readInteger :: String -> Maybe Integer
readInteger s =
  case reads s of
    [(n, "")] -> Just n
    _         -> Nothing

parseOpts :: [String] -> IO (Options, [String])
parseOpts argv =
   case getOpt Permute options argv of
      (o,n,[]  ) -> return (foldl (flip id) defaultOptions o, n)
      (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
  where header = "Usage: ic [OPTION...] files..."
