content: {-# LANGUAGE DeriveDataTypeable        #-}
  {-# LANGUAGE FlexibleContexts          #-}
  {-# LANGUAGE FlexibleInstances         #-}
  {-# LANGUAGE MultiParamTypeClasses     #-}
  {-# LANGUAGE NoMonomorphismRestriction #-}
  {-# LANGUAGE OverloadedStrings         #-}
  {-# LANGUAGE RecordWildCards           #-}
  {-# LANGUAGE ScopedTypeVariables       #-}
  {-# LANGUAGE TypeFamilies              #-}
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Aws.DynamoDb.Commands.UpdateItem
  -- Copyright   :  Soostone Inc
  -- License     :  BSD3
  --
  -- Maintainer  :  Ozgun Ataman <ozgun.ataman@soostone.com>
  -- Stability   :  experimental
  --
  --
  ----------------------------------------------------------------------------
  
  module Aws.DynamoDb.Commands.UpdateItem
      ( UpdateItem(..)
      , updateItem
      , AttributeUpdate(..)
      , au
      , UpdateAction(..)
      , UpdateItemResponse(..)
      ) where
  
  -------------------------------------------------------------------------------
  import           Control.Applicative
  import           Data.Aeson
  import qualified Data.Aeson.Key      as AK
  import           Data.Default
  import qualified Data.Text           as T
  import           Prelude
  -------------------------------------------------------------------------------
  import           Aws.Core
  import           Aws.DynamoDb.Core
  -------------------------------------------------------------------------------
  
  
  -- | An @UpdateItem@ request.
  data UpdateItem = UpdateItem {
        uiTable   :: T.Text
      , uiKey     :: PrimaryKey
      , uiUpdates :: [AttributeUpdate]
      , uiExpect  :: Conditions
      -- ^ Conditional update - see DynamoDb documentation
      , uiReturn  :: UpdateReturn
      , uiRetCons :: ReturnConsumption
      , uiRetMet  :: ReturnItemCollectionMetrics
      } deriving (Eq,Show,Read,Ord)
  
  
  -------------------------------------------------------------------------------
  -- | Construct a minimal 'UpdateItem' request.
  updateItem
      :: T.Text                   -- ^ Table name
      -> PrimaryKey               -- ^ Primary key for item
      -> [AttributeUpdate]        -- ^ Updates for this item
      -> UpdateItem
  updateItem tn key ups = UpdateItem tn key ups def def def def
  
  
  -- | A helper to avoid overlapping instances for 'ToJSON'.
  newtype AttributeUpdates = AttributeUpdates {
      getAttributeUpdates :: [AttributeUpdate]
      }
  
  
  data AttributeUpdate = AttributeUpdate {
        auAttr   :: Attribute
      -- ^ Attribute key-value
      , auAction :: UpdateAction
      -- ^ Type of update operation.
      } deriving (Eq,Show,Read,Ord)
  
  
  instance DynSize AttributeUpdate where
      dynSize (AttributeUpdate a _) = dynSize a
  
  -------------------------------------------------------------------------------
  -- | Shorthand for the 'AttributeUpdate' constructor. Defaults to PUT
  -- for the update action.
  au :: Attribute -> AttributeUpdate
  au a = AttributeUpdate a def
  
  
  instance ToJSON AttributeUpdates where
      toJSON = object . map mk . getAttributeUpdates
          where
            mk AttributeUpdate { auAction = UDelete, auAttr = auAttr } =
              (AK.fromText (attrName auAttr)) .= object
              ["Action" .= UDelete]
            mk AttributeUpdate { .. } = AK.fromText (attrName auAttr) .= object
              ["Value" .= (attrVal auAttr), "Action" .= auAction]
  
  
  -------------------------------------------------------------------------------
  -- | Type of attribute update to perform.
  --
  -- See AWS docs at:
  --
  -- @http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/APIReference\/API_UpdateItem.html@
  data UpdateAction
      = UPut                      -- ^ Simpley write, overwriting any previous value
      | UAdd                      -- ^ Numerical add or add to set.
      | UDelete                   -- ^ Empty value: remove; Set value: Subtract from set.
      deriving (Eq,Show,Read,Ord)
  
  
  instance ToJSON UpdateAction where
      toJSON UPut = String "PUT"
      toJSON UAdd = String "ADD"
      toJSON UDelete = String "DELETE"
  
  
  instance Default UpdateAction where
      def = UPut
  
  
  instance ToJSON UpdateItem where
      toJSON UpdateItem{..} =
          object $ expectsJson uiExpect ++
            [ "TableName" .= uiTable
            , "Key" .= uiKey
            , "AttributeUpdates" .= AttributeUpdates uiUpdates
            , "ReturnValues" .= uiReturn
            , "ReturnConsumedCapacity" .= uiRetCons
            , "ReturnItemCollectionMetrics" .= uiRetMet
            ]
  
  
  data UpdateItemResponse = UpdateItemResponse {
        uirAttrs    :: Maybe Item
      -- ^ Old attributes, if requested
      , uirConsumed :: Maybe ConsumedCapacity
      -- ^ Amount of capacity consumed
      } deriving (Eq,Show,Read,Ord)
  
  
  
  instance Transaction UpdateItem UpdateItemResponse
  
  
  instance SignQuery UpdateItem where
      type ServiceConfiguration UpdateItem = DdbConfiguration
      signQuery gi = ddbSignQuery "UpdateItem" gi
  
  
  instance FromJSON UpdateItemResponse where
      parseJSON (Object v) = UpdateItemResponse
          <$> v .:? "Attributes"
          <*> v .:? "ConsumedCapacity"
      parseJSON _ = fail "UpdateItemResponse expected a JSON object"
  
  
  instance ResponseConsumer r UpdateItemResponse where
      type ResponseMetadata UpdateItemResponse = DdbResponse
      responseConsumer _ _ ref resp = ddbResponseConsumer ref resp
  
  
  instance AsMemoryResponse UpdateItemResponse where
      type MemoryResponse UpdateItemResponse = UpdateItemResponse
      loadToMemory = return
  
  
  
  
  
  
  
  
  