              WriteRequest]
             com.amazonaws.ClientConfiguration
             com.amazonaws.auth.BasicAWSCredentials
-            com.amazonaws.services.dynamodb.AmazonDynamoDBClient
+            com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient
             java.nio.ByteBuffer))
 
 ;;;; TODO Rotary PRs


  The throughput is a map with two keys:
    :read  - the provisioned number of reads per second
    :write - the provisioned number of writes per second"
  [creds {:keys [name hash-key range-key throughput]}]
  (.createTable
   (db-client creds)
   (doto (CreateTableRequest.)
     (.setTableName (str name))
     (.setKeySchema (key-schema hash-key range-key))
     (.setProvisionedThroughput (provisioned-throughput throughput)))))

(defn update-table
  "Update a table in DynamoDB with the given name. Only the throughput may be

        op (->> operator name str/upper-case)]
    (operator-map (keyword op) op)))

;; (defn- query-request
;;   "Create a QueryRequest object."
;;   [table hash-key range-clause {:keys [order limit after count consistent attrs]}]
;;   (let [qr (QueryRequest. table (clj-val->db-val hash-key))
;;         [operator range-key range-end] range-clause]
;;     (when operator
;;       (set-range-condition qr (normalize-operator operator) range-key range-end))
;;     (when attrs
;;       (.setAttributesToGet qr (map name attrs)))
;;     (when order
;;       (.setScanIndexForward qr (not= order :desc)))
;;     (when limit
;;       (.setLimit qr (int limit)))
;;     (when count
;;       (.setCount qr count))
;;     (when consistent
;;       (.setConsistentRead qr consistent))
;;     (when after
;;       (.setExclusiveStartKey qr (item-key after)))
;;     qr))

(defn- query-request
  "Create a QueryRequest object."
  [table hash-key range-clause {:keys [order limit after count consistent attrs]}] ;; TODO +index
  (let [qr (QueryRequest.)
        hash-clause (set-hash-condition hash-key)
        [range-key operator range-value range-end] range-clause
        query-conditions (if-not operator
                           hash-clause
                           (merge hash-clause (set-range-condition range-key
                                                                   (normalize-operator operator)
                                                                   range-value
                                                                   range-end)))]
    (.setTableName qr table)
    (.setKeyConditions qr query-conditions)
    (when attrs      (.setAttributesToGet qr (map name attrs)))
    (when order      (.setScanIndexForward qr (not= order :desc)))
    (when limit      (.setLimit qr (int limit)))
    (when count      (.setCount qr count))
    (when consistent (.setConsistentRead qr consistent))
    (when after      (.setExclusiveStartKey qr (item-key after)))
    ;; (when index      (.setIndexName qr index)) ; TODO
    qr))

(defn- extract-range [[range options]]
  (if (and (map? range) (not options))
    [nil range]
    [range options]))

;; (defn query
;;   "Return the items in a DynamoDB table matching the supplied hash key.
;;   Can specify a range clause if the table has a range-key ie. `(>= 234)
;;   Takes the following options:
;;     :order - may be :asc or :desc (defaults to :asc)
;;     :attrs - limit the values returned to the following attribute names
;;     :limit - the maximum number of items to return
;;     :after - only return results after this key
;;     :consistent - return a consistent read if logical true

;;   The items are returned as a map with the following keys:
;;     :items    - the list of items returned
;;     :count    - the count of items matching the query
;;     :last-key - the last evaluated key (useful for paging)"
;;   [creds table hash-key & range-and-options]
;;   (let [[range options] (extract-range range-and-options)]
;;     (result-map
;;      (.query
;;       (db-client creds)
;;       (query-request table hash-key range options)))))

(defn query
  "Return the items in a DynamoDB table matching the supplied hash key,
  defined in the form {\"hash-attr\" hash-value}.
  Can specify a range clause if the table has a range-key ie. `(\"range-attr\" >= 234)
  Takes the following options:
    :order - may be :asc or :desc (defaults to :asc)
    :attrs - limit the values returned to the following attribute names
    :limit - the maximum number of items to return
    :after - only return results after this key
    :consistent - return a consistent read if logical true
;;    :index - the secondary index to query ; TODO

  The items are returned as a map with the following keys:
    :items - the list of items returned
    :count - the count of items matching the query
    :last-key - the last evaluated key (useful for paging)"
  [creds table hash-key & range-and-options]
  (let [[range options] (extract-range range-and-options)]
