content: {-# LANGUAGE FlexibleContexts      #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE TupleSections         #-}
  module Aws.Iam.Internal
      ( iamAction
      , iamAction'
      , markedIter
      , markedIterResponse
  
      -- * Re-exports
      , (<>)
      ) where
  
  import           Aws.Core
  import           Aws.Iam.Core
  import           Control.Applicative
  import           Control.Arrow       (second)
  import           Control.Monad
  import           Control.Monad.Trans.Resource (MonadThrow)
  import           Data.ByteString     (ByteString)
  import           Data.Maybe
  import           Data.Monoid
  import           Prelude
  import           Data.Text           (Text)
  import qualified Data.Text           as Text
  import qualified Data.Text.Encoding  as Text
  import           Text.XML.Cursor     (($//))
  import qualified Text.XML.Cursor     as Cu
  
  -- | Similar to 'iamSignQuery'. Accepts parameters in @Text@ form and UTF-8
  -- encodes them. Accepts the @Action@ parameter separately since it's always
  -- required.
  iamAction
      :: ByteString
      -> [(ByteString, Text)]
      -> IamConfiguration qt
      -> SignatureData
      -> SignedQuery
  iamAction action = iamSignQuery
                   . (:) ("Action", action)
                   . map (second Text.encodeUtf8)
  
  -- | Similar to 'iamAction'. Accepts parameter list with @Maybe@ parameters.
  -- Ignores @Nothing@s.
  iamAction'
      :: ByteString
      -> [Maybe (ByteString, Text)]
      -> IamConfiguration qt
      -> SignatureData
      -> SignedQuery
  iamAction' action = iamAction action . catMaybes
  
  -- | Returns the parameters @Marker@ and @MaxItems@ that are present in all
  -- IAM data pagination requests.
  markedIter :: Maybe Text -> Maybe Integer -> [Maybe (ByteString, Text)]
  markedIter marker maxItems
      = [ ("Marker"  ,)                 <$> marker
        , ("MaxItems",) . encodeInteger <$> maxItems
        ]
    where
      encodeInteger = Text.pack . show
  
  -- | Reads and returns the @IsTruncated@ and @Marker@ attributes present in
  -- all IAM data pagination responses.
  markedIterResponse
      :: MonadThrow m
      => Cu.Cursor
      -> m (Bool, Maybe Text)
  markedIterResponse cursor = do
      isTruncated <- (Text.toCaseFold "true" ==) `liftM` attr "IsTruncated"
      marker      <- if isTruncated
                      then Just `liftM` attr "Marker"
                      else return Nothing
      return (isTruncated, marker)
    where
      attr name = force ("Missing " ++ Text.unpack name) $
                  cursor $// elContent name
  