{-# LANGUAGE FlexibleContexts #-}
-- | handle the authorization mecanism for Instagram
-- <http://instagram.com/developer/authentication/#>
module Instagram.Auth (
  RedirectUri,
  getUserAccessTokenURL1,
  getUserAccessTokenURL2
) where

import Instagram.Monad
import Instagram.Types

import Data.Text hiding (map)
import Control.Monad (liftM)
import qualified Data.ByteString as BS (ByteString,intercalate)
import qualified Data.Text.Encoding as TE
import qualified Network.HTTP.Types as HT


-- | the URI to redirect the user after she accepts/refuses to authorize the app
type RedirectUri = Text

-- | get the authorize url to redirect your user to
getUserAccessTokenURL1 :: Monad m =>
  RedirectUri -- ^ the URI to redirect the user after she accepts/refuses to authorize the app
  -> [Scope] -- ^ the requested scopes (can be empty for Basic)
  -> InstagramT m Text -- ^ the URL to redirect the user to
getUserAccessTokenURL1 url scopes=  do
  cid<-liftM clientIDBS getCreds
  bsurl<-getQueryURL "/oauth/authorize/" $ buildQuery cid ++ buildScopes scopes
  return $ TE.decodeUtf8 bsurl
  where
    -- | build the query with client id and redirect URI
    buildQuery :: BS.ByteString -> HT.SimpleQuery
    buildQuery cid=[("client_id",cid),("redirect_uri",TE.encodeUtf8 url),("response_type","code")]
    buildScopes ::  [Scope] ->  HT.SimpleQuery
    buildScopes []=[]
    buildScopes l =[("scope",BS.intercalate "+" $ map (TE.encodeUtf8 . toLower . pack . show) l)]

-- | second step of authorization: get the access token once the user has been redirected with a code
getUserAccessTokenURL2 :: (MonadBaseControl IO m, MonadResource m) =>
  RedirectUri -- ^ the redirect uri
  -> Text -- ^ the code sent back to your app
  -> InstagramT m OAuthToken -- ^ the auth token
getUserAccessTokenURL2 url code=
  addClientInfos buildQuery >>= getPostRequest "/oauth/access_token" >>= getJSONResponse
  where
    -- | build query parameters
    buildQuery ::  HT.SimpleQuery
    buildQuery =[("redirect_uri",TE.encodeUtf8 url),("grant_type","authorization_code"),
        ("code",TE.encodeUtf8 code)]