   (lsb/write-long w (:aligned-alns meta-data))
   (lsb/write-long w (:unaligned-alns meta-data)))
 
-; bins bins-seen lidx meta-data
-; @bins @bins-seen (optimize-lidx lidx @largest-lidx-seen) @meta-data
-
-(defn- write-ref*
-  [^DataOutputStream w bins bins-seen lidx meta-data]
-  (let [size (if (seq bins) bins-seen 0)]
-    (if (zero? size)
-      (write-null-content w)
-      (do
-        ;; n_bin
-        (lsb/write-int w (inc size))
-        ;; bins
-        (doseq [bin bins]
-          (when-not (nil? bin)
-           (when-not (= (:bin-num bin) max-bins)
-             (write-bin w bin))))
-        ;; meta data
-        (write-meta-data w meta-data)
-        ;; n_intv
-        (lsb/write-int w (count lidx))
-        ;; intv
-        (doseq [l lidx]
-          (lsb/write-long w l))))))
-
-(defn- write-ref!
-  [^DataOutputStream w ^BAIWriterStatus s]
-  (write-ref* w
-              @(:bins s)
-              @(:bins-seen s)
-              (optimize-lidx (:lidx s) @(:largest-lidx-seen s))
-              @(:meta s)))
-
-(defn- next-ref!
-  [^BAIWriterStatus s]
-  (swap! (:idx s) inc)
-  (reset! (:ref-name s) (:name (current-ref s)))
-  (reset! (:bins s) (gen-vec (bin-count (:refs s) @(:idx s))))
-  (reset! (:bins-seen s) 0)
-  (reset! (:lidx s) (gen-vec max-lidx-size 0))
-  (reset! (:largest-lidx-seen s) -1)
-  (swap! (:meta s) assoc :first-offset -1, :last-offset 0, :aligned-alns 0, :unaligned-alns 0))
-
-(defn- write-no-coordinate-alns-count
-  [^DataOutputStream w meta-data]
-  (lsb/write-long w (:no-coordinate-alns meta-data)))
-
-(defn- write-index*
-  [^DataOutputStream w ^BAIWriterStatus s aln]
-  (when @(:valid s)
-    (when-not (= (:rname aln) @(:ref-name s))
-      (if (has-next? s)
-        (do
-          ;; Write data about current ref
-          (write-ref! w s)
-          ;; Set next ref
-          (next-ref! s))
-        (reset! (:valid s) false))))
-  (when @(:valid s)
+;;
+;; index
+;;
+
+(defn- make-index!
+  [refs alns]
+  (let [indices (atom {})
+        ref-name (atom nil)
+        bins (atom nil)
+        bins-seen (atom 0)
+        lidx (atom (gen-vec max-lidx-size 0))
+        largest-lidx-seen (atom -1)
+        meta (atom {:first-offset -1
+                    :last-offset 0
+                    :aligned-alns 0
+                    :unaligned-alns 0})
+        no-coordinate-alns (atom 0)]
     ;; meta data
-    (let [meta (:meta s)]
+    (doseq [aln alns]
+      (when (nil? @ref-name)
+        (reset! ref-name (:rname aln))
+        (reset! bins (gen-vec (bin-count refs (:rname aln)))))
+      (when-not (= (:rname aln) @ref-name)
+        (swap! indices assoc @ref-name {:meta @meta
+                                        :bins @bins
+                                        :lidx (optimize-lidx lidx @largest-lidx-seen)})
+        (reset! ref-name (:rname aln))
+        (reset! bins (gen-vec (bin-count refs (:rname aln))))
+        (reset! bins-seen 0)
+        (reset! lidx (gen-vec max-lidx-size 0))
+        (reset! largest-lidx-seen -1)
+        (reset! meta {:first-offset -1
+                      :last-offset 0
+                      :aligned-alns 0
+                      :unaligned-alns 0}))
       (if (zero? (:pos aln))
-        (swap! meta update-in [:no-coordinate-alns] inc)
+        (swap! no-coordinate-alns inc)
         (do (if-not (zero? (bit-and (:flag aln) 4))
               (swap! meta update-in [:unaligned-alns] inc)
               (swap! meta update-in [:aligned-alns] inc))

        (recur (inc i))))
    @new-lidx))

(defn- write-null-content
  [w]
  (lsb/write-long w 0))

(defn- write-bin
  [w bin]
  {:pre (< (:bin-num bin) max-bins)}
  ;; bin
  (lsb/write-int w (:bin-num bin))
  ;; chunks
  (lsb/write-int w (count (:chunks bin)))
  (doseq [c (:chunks bin)]

              (swap! meta assoc :first-offset (:beg (:chunk (:meta aln)))))
            (if (< (bgzf-util/compare (:last-offset @meta)
                                      (:end (:chunk (:meta aln)))) 1)
              (swap! meta assoc :last-offset (:end (:chunk (:meta aln)))))))
      ;; bins
      (let [chunk-beg (:beg (:chunk (:meta aln)))
            chunk-end (:end (:chunk (:meta aln)))]
        (let [bin-idx (sam-util/compute-bin aln)
              bin (if (nil? (nth @bins bin-idx))
                    (do
                      (swap! bins assoc bin-idx {:idx bin-idx, :chunks nil})
                      (swap! bins-seen inc)
                      (nth @bins bin-idx))
                    (nth @bins bin-idx))]
          ;; chunk
          (if (seq (:chunks bin))
            (if (bgzf-util/same-or-adjacent-blocks? (:end (last (:chunks bin)))
                                                    chunk-beg)
              (let [last-idx (dec (count (:chunks bin)))
                    last-chunk (last (:chunks bin))
                    new-chunks (assoc (:chunks bin) last-idx (assoc last-chunk :end chunk-end))
                    new-bin (assoc bin :chunks new-chunks)]
                (swap! bins assoc bin-idx new-bin))
              (let [new-bin (update-in bin [:chunks] conj (:chunk (:meta aln)))]
                (swap! bins assoc bin-idx new-bin)))
            (let [new-bin (assoc bin :chunks (vector (:chunk (:meta aln))))]
              (swap! bins assoc bin-idx new-bin))))
        ;; lenear index
        (let [aln-beg (:pos aln)
              aln-end (+ aln-beg (cgr/count-ref (:cigar aln)))
