   (:import [gclouj DatastoreOptionsFactory]
            [java.io InputStream]
            [java.nio ByteBuffer]
-           [com.google.cloud.datastore DatastoreOptions Entity FullEntity DatastoreOptions$DefaultDatastoreFactory Transaction Key IncompleteKey DatastoreBatchWriter EntityValue ValueType StringValue LongValue DoubleValue DateTime DateTimeValue BooleanValue BlobValue Blob ListValue NullValue Value KeyValue FullEntity$Builder Query StructuredQuery$PropertyFilter StructuredQuery$CompositeFilter StructuredQuery$Filter StructuredQuery$OrderBy]
+           [com.google.cloud.datastore DatastoreOptions FullEntity Entity FullEntity DatastoreOptions$DefaultDatastoreFactory Transaction Key IncompleteKey DatastoreBatchWriter EntityValue ValueType StringValue LongValue DoubleValue DateTime DateTimeValue BooleanValue BlobValue Blob ListValue NullValue Value KeyValue FullEntity$Builder Query StructuredQuery$PropertyFilter StructuredQuery$CompositeFilter StructuredQuery$Filter StructuredQuery$OrderBy]
            [com.google.cloud AuthCredentials]))
 
 (defn credential-options [project-id namespace json-key]

(defn byte-array? [x]
  (= (Class/forName "[B") (class x)))

(defn property-value [x]
  (cond (nil? x)                      (NullValue. )
        (float? x)                    (DoubleValue/of x)
        (number? x)                   (LongValue/of x)

        (or (byte-array? x)
            (instance? InputStream x)
            (instance? ByteBuffer x)) (BlobValue/of (Blob/copyFrom x))
        (sequential? x)               (ListValue/of (map to-value x))
        (instance? FullEntity x)      (EntityValue/of x)
        (map? x)                      (EntityValue/of (entity x))
        :else      x))

(defn- map->entity
  [builder m]
  (doseq [[k v] m]
    (if (map? v)
      (.set builder k ^FullEntity (entity v))
      (.set builder k ^Value (to-value v))))
  builder)

(defn entity
  "Converts a Clojure map into a Datastore Entity. Recursively converts
  all values into an entity or value using property-value. Keys must all
  be strings."
  ([m] (let [b (FullEntity/builder)]
         (.build (map->entity b m))))
  ([k m] (let [b (cond
                   (instance? Key k)           (Entity/builder k)
                   (instance? IncompleteKey k) (FullEntity/builder k))]
           (.build (map->entity b m)))))

(defprotocol ToClojure
  (to-clojure [x]))
