   (:use [clojure.contrib.def :only [defnk]])
   (:import [com.mongodb Mongo DB DBCollection BasicDBObject
             DBObject DBCursor DBAddress MongoOptions
-            ObjectId]))
+            ObjectId]
+           [java.util Calendar]))
+
+(defn date [& [year month date hour minute second milli]]
+  (let [c  (Calendar/getInstance)
+        z? #(int (or % 0))]
+    (.set c Calendar/YEAR        (z? year))
+    (.set c Calendar/MONTH       (z? (- month 1)))
+    (.set c Calendar/DATE        (z? date))
+    (.set c Calendar/HOUR_OF_DAY (z? hour))
+    (.set c Calendar/MINUTE      (z? minute))
+    (.set c Calendar/SECOND      (z? second))
+    (.set c Calendar/MILLISECOND (z? milli))
+    (.getTime c)))
 
 (defn has-option? [options k]
   (boolean (some #{k} options)))
 
-(defn db-object [m]
+(defn to-dbo [m]
   (let [to-s #(if (keyword? %) (name %) (str %))
-        to-v #(if (map? %) (db-object %) %)
+        to-v #(if (map? %) (to-dbo %) %)
         dbo  (BasicDBObject.)]
     (doseq [[k v] m]
       (.put dbo (to-s k) (to-v v)))
     dbo))
 
-(defn clojure-object [dbo]
+(defn to-clj [dbo]
   (apply merge (map (fn [#^java.util.Map$Entry e]
                        (let [k (.getKey e)
                              v (.getValue e)]
                          {(keyword k)
                           (if (instance? DBObject v)
-                            (clojure-object v)
+                            (to-clj v)
                             v)}))
                     (seq dbo))))
 


(defn insert [#^DBCollection collection & objs]
  (if (= 1 (count objs))
    (clojure-object
     (.insert collection #^DBObject (db-object (first objs))))
    (map clojure-object
         (.insert collection #^java.util.List (map db-object objs)))))

(defn update [#^DBCollection collection query obj & options]
  (let [o? #(has-option? options %)]
    (clojure-object (.update collection
                             (db-object query)
                             (db-object obj)
                             (o? :upsert)
                             (o? :multi)))))


  [#^DBCollection collection fields & options]
  (let [o? #(has-option? options %)]
    (.ensureIndex collection #^DBObject
                  (to-dbo fields)
                  (boolean (o? :force))
                  (boolean (o? :unique)))))

(defn drop-index [#^DBCollection collection o]
  (.dropIndex collection #^DBObject (to-dbo o)))

(defn drop-index-named [#^DBCollection collection kw]
  (.dropIndex collection (name kw)))

