-- | Provides IO action that parses command line options and tweets from stdin
module Web.Tweet.Exec ( exec
                      , Program (Program)) where

import Web.Tweet
import Options.Applicative
import qualified Data.ByteString.Char8 as BS
import Control.Monad
import Data.Foldable (fold)
import Data.Monoid

-- | Data type for our program: one optional path to a credential file, (optionally) the number of tweets to make, the id of the status you're replying to, and a list of users you wish to mention.
data Program = Program { cred :: Maybe FilePath , tweets :: Maybe Int, replyId :: Maybe String, replyHandles :: Maybe [String] }

-- | query twitter to post stdin with no fancy options
fromStdIn :: Int -> FilePath -> IO ()
fromStdIn = threadStdIn [] Nothing

-- | Threaded tweets from stdIn
threadStdIn :: [String] -> Maybe Int -> Int -> FilePath -> IO ()
threadStdIn hs idNum num filepath = do
    contents <- getContents
    thread contents hs idNum num filepath

-- | Executes parser
exec :: IO ()
exec = execParser opts >>= select
    where
        opts = info (helper <*> program)
            (fullDesc
            <> progDesc "Tweet from stdin!"
            <> header "clit - a Command Line Interface Tweeter")

-- | Executes program
select :: Program -> IO ()
select (Program Nothing (Just n) Nothing Nothing) = fromStdIn n ".cred"
select (Program Nothing Nothing Nothing Nothing) = fromStdIn 4 ".cred"
select (Program (Just file) (Just n) Nothing Nothing) = fromStdIn n file
select (Program (Just file) Nothing Nothing Nothing) = fromStdIn 4 file
select (Program Nothing (Just n) (Just id) (Just handles)) = threadStdIn handles (read id) n ".cred"
select (Program (Just file) (Just n) (Just id) (Just handles)) = threadStdIn handles (pure . read $ id) n file
select (Program (Just file) Nothing (Just id) (Just handles)) = threadStdIn handles (pure . read $ id) 4 file
select (Program Nothing (Just n) (Just id) Nothing) = threadStdIn [] (pure . read $ id) n ".cred"
select (Program Nothing Nothing (Just id) Nothing) = threadStdIn [] (pure . read $ id) 4 ".cred"
select (Program Nothing Nothing (Just id) (Just handles)) = threadStdIn handles (pure . read $ id) 4 ".cred"
select (Program (Just file) (Just n) (Just id) Nothing) = threadStdIn [] (pure . read $ id) n file
select (Program (Just file) (Just n) Nothing (Just handles)) = threadStdIn handles Nothing n file

-- | Parser to return a program datatype
program :: Parser Program
program = Program
    <$> (optional $ strOption
        (long "cred"
        <> short 'c'
        <> metavar "CREDENTIALS"
        <> help "path to credentials"))
    <*> (optional $ read <$> strOption
        (long "tweets"
        <> short 't'
        <> metavar "NUM"
        <> help "Number of tweets in a row, default 4"))
    <*> (optional $ strOption
        (long "reply"
        <> short 'r'
        <> help "id of status to reply to - be sure to include their handle, e.g. @my_build_errors"))
    <*> (optional $ some $ argument str
        (metavar "HANDLE1"
        <> help "handles to include in replies"))