module Reddit.Login
  ( login ) where

import Reddit.Types.Error
import Reddit.Types.Reddit

import Control.Concurrent (threadDelay)
import Control.Concurrent.STM.TVar
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Trans.Except
import Control.Monad.Trans.State
import Data.Text (Text)
import Network.API.Builder
import Network.HTTP.Conduit

loginRoute :: Text -> Text -> Route
loginRoute user pass = Route [ "api", "login" ]
                             [ "rem" =. True
                             , "user" =. user
                             , "passwd" =. pass ]
                             "POST"

getLoginDetails :: MonadIO m => Text -> Text -> RedditT m LoginDetails
getLoginDetails user pass = do
  resp <- RedditT $ sendRoute () $ loginRoute user pass
  let cj = responseCookieJar resp
  case unwrapJSON `fmap` receive resp of
    Left x@(APIError (RateLimitError wait _)) -> do
      RateLimits limiting _ <- RedditT $ liftState get >>= liftIO . readTVarIO
      if limiting
        then do
          liftIO $ threadDelay $ (fromIntegral wait + 5) * 1000000
          getLoginDetails user pass
        else RedditT $ ExceptT $ return $ Left x
    Left x -> RedditT $ ExceptT $ return $ Left x
    Right modhash -> return $ LoginDetails modhash cj


-- | Make a login request with the given username and password.
login :: MonadIO m
      => Text -- ^ Username to login with
      -> Text -- ^ Password to login with
      -> RedditT m LoginDetails
login user pass = do
  RedditT $ baseURL loginBaseURL
  d <- getLoginDetails user pass
  RedditT $ baseURL mainBaseURL
  return d