-- | Miscellaneous functions that don't fit the project directly
module Web.Tweet.Utils (
    hits
  , getTweets
  , displayTimeline
  , displayTimelineColor
  , lineByKey
  , getConfigData ) where

import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString as BS2
import Data.List
import Web.Tweet.Types
import Control.Lens hiding (noneOf)
import Web.Tweet.Utils.Colors
import Data.List.Extra
import Web.Tweet.Parser
import Text.Megaparsec

-- | filter out retweets, and sort by most successful.
hits :: Timeline -> Timeline
hits = sortTweets . filterRTs 

-- | Filter out retweets
filterRTs :: Timeline -> Timeline
filterRTs = filter ((/="RT @") . take 4 . (view text))

-- | Filter out quotes
filterQuotes :: Timeline -> Timeline
filterQuotes = filter ((==Nothing) . (view quoted))

-- | Get a list of tweets from a response, returning author, favorites, retweets, and content. 
getTweets :: BS2.ByteString -> Either (ParseError Char Dec) Timeline
getTweets = parse parseTweet "" 

-- | Display Timeline without color
displayTimeline :: Timeline -> String
displayTimeline ((TweetEntity content user screenName idTweet Nothing rts fave):rest) = concat [user
    , " ("
    , screenName
    , ")"
    ,":\n    " 
    ,fixNewline content 
    ,"\n    " 
    ,"♥ " 
    ,show fave 
    ," ♺ " 
    ,show rts 
    , "  "
    , show idTweet
    ,"\n\n" 
    ,displayTimeline rest]
displayTimeline ((TweetEntity content user screenName idTweet (Just quoted) rts fave):rest) = concat [user 
    , " ("
    , screenName
    , ")"
    , ":\n    " 
    , fixNewline content 
    , "\n    " 
    , "♥ " 
    , show fave 
    , " ♺ " 
    , show rts 
    , "  "
    , show idTweet
    , "\n    " 
    , _name quoted 
    , " ("
    , _screenName quoted
    , ")"
    , ": " 
    , _text quoted 
    , "\n\n" 
    , displayTimeline rest]
displayTimeline [] = []

-- | Display Timeline in color
displayTimelineColor :: Timeline -> String
displayTimelineColor ((TweetEntity content user screenName idTweet Nothing rts fave):rest) = concat [toYellow user 
    , " ("
    , screenName
    , ")"
    , ":\n    " 
    , fixNewline content
    , "\n    " 
    , toRed "♥"
    , " "
    , show fave 
    , toGreen " ♺ " 
    , show rts 
    , "  "
    , toBlue (show idTweet)
    , "\n\n" 
    , displayTimelineColor rest]
displayTimelineColor ((TweetEntity content user screenName  idTweet (Just quoted) rts fave):rest) = concat [toYellow user 
    , " ("
    , screenName
    , ")"
    , ":\n    " 
    , fixNewline content 
    , "\n    " 
    , toRed "♥"
    , " "
    , show fave 
    , toGreen " ♺ " 
    , show rts 
    , "  "
    , toBlue (show idTweet)
    , "\n    " 
    , toYellow $ _name quoted 
    , " ("
    , _screenName quoted
    , ")"
    , ": " 
    , _text quoted 
    , "\n\n" 
    , displayTimelineColor rest]
displayTimelineColor [] = []

-- | When displaying, newlines should include indentation.
fixNewline :: String -> String
fixNewline = replace "\n" "\n    "

-- | sort tweets by most successful
sortTweets :: Timeline -> Timeline
sortTweets = sortBy compareTweet
    where compareTweet (TweetEntity _ _ _ _ _ r1 f1) (TweetEntity _ _ _ _ _ r2 f2) = compare (2*r2 + f2) (2*r1 + f1)

-- | helper function to get the key as read from a file
keyLinePie :: String -> String
keyLinePie = takeWhile (/=':')

-- | Pick out a key value from a key
lineByKey :: BS.ByteString -> [(BS.ByteString, BS.ByteString)] -> BS.ByteString
lineByKey key = snd . head . (filter (\i -> fst i == key))

-- | Filter a line of a file for only the actual data and no descriptors
filterLine :: String -> String
filterLine = reverse . (takeWhile (not . (`elem` (" :" :: String)))) . reverse

-- | Get pairs of "key" to search for and actual values
getConfigData :: FilePath -> IO [(BS.ByteString, BS.ByteString)]
getConfigData filepath = zip <$> keys <*> content
    where content = (map (BS.pack . filterLine)) . lines <$> file
          keys    = (map (BS.pack . keyLinePie)) . lines <$> file
          file    = readFile filepath