   (:require [org.micromanager.mm :as mm])
   (:use [org.micromanager.mm :only (core)]))
 
-(def native-order (ByteOrder/nativeOrder))
+;; bucket brigade
 
-(defn byte-buffer
-  "Create a direct byte-buffer with native order."
-  [size-bytes]
-  (.. ByteBuffer (allocateDirect size-bytes)
-      (order native-order)))
+(defn bucket-node [input-queue function output-queue]
+  (future
+    (loop []
+      (let [item (.take input-queue)]
+        (if (= item input-queue)
+          (.put output-queue output-queue)
+          (do (.put output-queue (function item))
+              (recur)))))))
 
-(defn image-to-byte-buffer
-  "Store 16-bit image pixel array data in a
-   pre-existing byte buffer instance."
-  [pix buffer]
-  (.. buffer asShortBuffer (put pix))
-  buffer)
+(defn first-node [n function output-queue]
+  (future
+    (dotimes [i n]
+      (.put output-queue (function)))
+    (.put output-queue output-queue)))
+
+(defn last-node [input-queue function]
+  (loop []
+    (let [item (.take input-queue)]
+      (when (not= item input-queue)
+        (function item)
+        (recur)))))
+        
+
+(defn bucket-brigade [n & functions]
+  (let [first-queue (LinkedBlockingQueue.)
+        first-node (first-node n (first functions) first-queue)]
+    (loop [remaining-functions (rest functions) input-queue first-queue]
+      (let [f (first remaining-functions)]
+        (if-let [n (next remaining-functions)]
+          (let [output-queue (LinkedBlockingQueue.)]
+            (bucket-node input-queue f output-queue)
+            (recur n output-queue))
+          (last-node input-queue f))))))
+      
+;; acquiring and popping images
 
 (defn run-sequence-acquisition
   "Start a sequence acquisition and, optionally, wait for it."

        (.write channel buffer))
      (catch Exception e (println e))
      (finally
        (.close file)))))
      
    

(defn monitor-circular-buffer []
  (while (not (core isSequenceRunning))

    (println (core getRemainingImageCount))
    (Thread/sleep 250)))

(defn drain-queue [blocking-queue]
  (future (loop [i 0]
            (let [obj (.take blocking-queue)]
              (when (zero? (mod i 100))
                (println i (core getRemainingImageCount)))
              (when (not= obj blocking-queue)
                (recur (inc i)))))))

(defn profile [repetitions f]
  (time (dorun (repeatedly repetitions f))))

(defn test-popping-speed [n]
  ;(future (monitor-circular-buffer))
  (core startSequenceAcquisition n 0 false)
 ; (time (while (core isSequenceRunning)
 ;         (Thread/sleep 1)))
  (profile n #(pop-next-image)))

(defn extract-array [short-buf]
  (.rewind short-buf)
  (let [n (.limit short-buf)
        a (short-array n)]
    (.get short-buf a 0 n)
    a))
  
(defn extract-array-test [n]
  (let [short-buf (.asShortBuffer (byte-buffer (* 2 2560 2160)))]
    (profile n #(extract-array short-buf))))
  

