content: {-# LANGUAGE DeriveDataTypeable        #-}
  {-# LANGUAGE FlexibleContexts          #-}
  {-# LANGUAGE FlexibleInstances         #-}
  {-# LANGUAGE MultiParamTypeClasses     #-}
  {-# LANGUAGE NoMonomorphismRestriction #-}
  {-# LANGUAGE OverloadedStrings         #-}
  {-# LANGUAGE RecordWildCards           #-}
  {-# LANGUAGE ScopedTypeVariables       #-}
  {-# LANGUAGE TypeFamilies              #-}
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Aws.DynamoDb.Commands.BatchWriteItem
  -- Copyright   :  Soostone Inc
  -- License     :  BSD3
  --
  -- Maintainer  :  Justin Dawson <jtdawso@gmail.com>
  -- Stability   :  experimental
  --
  -- @http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/APIReference\/API_BatchWriteItem.html@
  ----------------------------------------------------------------------------
  
  module Aws.DynamoDb.Commands.BatchWriteItem where
  
  -------------------------------------------------------------------------------
  import           Control.Applicative
  import           Data.Aeson
  import           Data.Default
  import           Data.Foldable (asum)
  import qualified Data.HashMap.Strict as HM
  import qualified Data.Text           as T
  import           Prelude
  -------------------------------------------------------------------------------
  import           Aws.Core
  import           Aws.DynamoDb.Core
  import           Aws.DynamoDb.Commands.PutItem
  import           Aws.DynamoDb.Commands.DeleteItem
  -------------------------------------------------------------------------------
  
  
  data Request = PutRequest { prItem :: Item }
               | DeleteRequest {drKey :: PrimaryKey}
       deriving (Eq,Show,Read,Ord)
  
  data BatchWriteItem = BatchWriteItem {
        bwRequests :: [(T.Text,[Request])]
      -- ^ Put or Delete Requests for a specified table
      , bwRetCons :: ReturnConsumption
      , bwRetMet  :: ReturnItemCollectionMetrics
      } deriving (Eq,Show,Read,Ord)
  
  
  -------------------------------------------------------------------------------
  
  toBatchWrite :: [PutItem]
             -> [DeleteItem]
             -> BatchWriteItem
  toBatchWrite ps ds =BatchWriteItem maps def def  
        where
          maps :: [(T.Text,[Request])]
          maps = let pMap = foldl (\acc p -> let key = piTable p
                                               in HM.insert key (PutRequest (piItem p) : (HM.lookupDefault [] key acc)) acc) HM.empty ps 
                     totalMap = foldl (\acc d -> let key = diTable d
                                                   in  HM.insert key (DeleteRequest (diKey d) : (HM.lookupDefault [] key acc)) acc) pMap ds
                   in  HM.toList totalMap
  -- | Construct a BatchWriteItem
  batchWriteItem :: [(T.Text,[Request])]
                 -> BatchWriteItem
  batchWriteItem reqs = BatchWriteItem reqs def def
  
  
  instance ToJSON Request where
     toJSON PutRequest{..} =
         object $
           [ "PutRequest" .= (object $ ["Item" .= prItem])
           ]
     toJSON DeleteRequest{..} =
         object $
           [ "DeleteRequest" .=  (object $ ["Key" .= drKey])
           ]
  
  instance ToJSON BatchWriteItem where
      toJSON BatchWriteItem{..} =
          object $
            [ "RequestItems" .= HM.fromList bwRequests
            , "ReturnConsumedCapacity" .= bwRetCons
            , "ReturnItemCollectionMetrics" .= bwRetMet
            ]
  
  instance FromJSON Request where
      parseJSON = withObject "PutRequest or DeleteRequest" $ \o ->
       
       asum [
             do
               pr <- o .: "PutRequest"
               i  <- pr .: "Item"
               return $ PutRequest i ,
             do
               dr <- o .: "DeleteRequest"
               pk <- dr .: "Key"
               return $ DeleteRequest pk
            ]
      
  data BatchWriteItemResponse = BatchWriteItemResponse {
        bwUnprocessed    :: [(T.Text,[Request])]
      -- ^ Unprocessed Requests on failure
      , bwConsumed :: Maybe ConsumedCapacity
      -- ^ Amount of capacity consumed
      , bwColMet   :: Maybe ItemCollectionMetrics
      -- ^ Collection metrics for tables affected by BatchWriteItem.
      } deriving (Eq,Show,Read,Ord)
  
  
  
  instance Transaction BatchWriteItem BatchWriteItemResponse
  
  
  instance SignQuery BatchWriteItem where
      type ServiceConfiguration BatchWriteItem = DdbConfiguration
      signQuery gi = ddbSignQuery "BatchWriteItem" gi
  
  
  instance FromJSON BatchWriteItemResponse where
      parseJSON (Object v) = BatchWriteItemResponse
          <$> HM.toList <$> (v .: "UnprocessedItems")
          <*> v .:? "ConsumedCapacity"
          <*> v .:? "ItemCollectionMetrics"
      parseJSON _ = fail "BatchWriteItemResponse must be an object."
  
  
  instance ResponseConsumer r BatchWriteItemResponse where
      type ResponseMetadata BatchWriteItemResponse = DdbResponse
      responseConsumer _ _ ref resp = ddbResponseConsumer ref resp
  
  
  instance AsMemoryResponse BatchWriteItemResponse where
      type MemoryResponse BatchWriteItemResponse = BatchWriteItemResponse
      loadToMemory = return
  