   (:require [aurora.btree :refer [tree iterator key-lt key-lte key-gt key-gte]])
   (:require-macros [aurora.macros :refer [typeof]]))
 
-(defn lt [a b]
+(defn nilless-lt [a b]
   (if (== a nil)
     false
     (or (and (identical? (typeof a) (typeof b))
              (< a b))
         (< (typeof a) (typeof b)))))
+
+(defn gt [a b]
+  (and (not (identical? a b))
+       (or (and (identical? (typeof a) (typeof b))
+                (> a b))
+           (> (typeof a) (typeof b)))))
+
+(defn lt [a b]
+  (and (not (identical? a b))
+       (or (and (identical? (typeof a) (typeof b))
+                (< a b))
+           (< (typeof a) (typeof b)))))
+
+(defn nilless-key-compare [as bs]
+  (let [as-len (alength as)
+        bs-len (alength bs)]
+    (assert (== as-len bs-len) (pr-str as bs))
+    (loop [i 0]
+      (if (< i as-len)
+        (let [a (aget as i)
+              b (aget bs i)]
+          (if (or (identical? a nil)
+                  (identical? b nil))
+            (recur (+ i 1))
+            (if (identical? a b)
+              (recur (+ i 1))
+              (if (lt a b)
+                -1
+                1))))
+        0))))
+
+(defn rewind-or-store
+  "Returns #js[ix, store?, rewind?]"
+  [as bs nil-ixs]
+  (let [len (alength nil-ixs)]
+    (loop [ix 0]
+      (if (< ix len)
+        (let [cur (aget nil-ixs ix)
+              rewind? (gt (aget as cur) (aget bs cur))]
+          (cond
+           (and (identical? cur 0) rewind?) #js [0 false rewind?]
+           (> cur 0) (let [store? (gt (aget as (- cur 1)) (aget bs (- cur 1)))]
+                       (if store?
+                         #js [cur store? false]
+                         (if rewind?
+                           #js [cur false rewind?]
+                           (recur (+ 1 ix)))))
+           :else (recur (+ 1 ix))))
+        #js [0 false false]))))
 
 (defn filled-key-compare [as bs fill]
   (let [as-len (alength as)

    (if (>= ix len)
      (do
        (aset min-fill col least)
        (let [next (inc col)]
          (if (< next tuple-len)
            (recur 0 next nil))))
      (let [cur (-> (aget keys ix)
                    (aget col))]
        (recur (inc ix) col (if (lt cur least)
                              cur
                              least))))))

(let [fill (array)]
  (find-least #js [#js [0 1 2] #js [nil 1 4] #js [nil 0 3]] 3 3 fill)
  (find-least #js [#js [0 1 2] #js [8 nil 10] #js [nil 9 10]] 3 3 fill)
  fill)

(defn find-greatest [iterators keys len results min-fill]
  (loop [ix 0
         greatest (aget keys 0)
         found? true]
    (if (>= ix len)

  (next [this]
        (.next iterator))
  (seek [this key]
        (when (key-lt (.key iterator) key)
          (.seek iterator key))))

(defn magic-iterator
  ([tree] (let [itr (iterator tree)]
            (MagicIteratorWrapper. itr (.key itr))))
  ([tree map]
   (let [nil-ixs (array)
         itr (iterator tree)
         marked-nodes (js-obj 0 (.-node itr))
         marked-ixs (js-obj 0 0)
         magic (MagicIterator. itr map nil-ixs (alength map) (array) (array) (.key itr) marked-nodes marked-ixs)]
     (dotimes [ix (alength map)]
       (when (identical? nil (aget map ix))
         (.push nil-ixs ix)))
     (.set-key magic)
     magic)))

(defn ->keys [iterators keys len]
  (dotimes [x len]
