 (ns engine.server.rope
+  "Implementation of Ropes as per \"Ropes: an Alternative to Strings\"
+by Boehm, Hans-J; Atkinson, Russ; and Plass, Michael (December 1995), doi:10.1002/spe.4380251203."
   (:use [clojure.string :only [join]])
   (:require [clojure.zip :as zip])
-  (:import [clojure.lang IPersistentCollection ITransientCollection Seqable Counted Indexed ISeq]
+  (:import [clojure.lang Counted Indexed]
            [java.lang String IndexOutOfBoundsException]))
 
 (def *fib-seq* (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
 (def *leaf-cutoff-length* 128)
 
 (defprotocol Measurable
-  (measure [object]))
+  "Trivial protocol for things measurable.
+Default implementations are provided for nil and String; nil measures as 0
+characters, 0 lines. Strings get analyzed accordingly."
+  (measure [object] "Measure object"))
 
 (defrecord CharSequenceMeasurement [#^int length #^int lines])
 
-(defn measurement [length lines]
+(defn measurement
+  "CharSequenceMeasurement from length and lines"
+  [length lines]
   (CharSequenceMeasurement. length lines))
 
-(defn count-matches [char string]
+(defn count-matches
+  "Number of character matches in string"
+  [char string]
   (->> string (filter #(= char %)) count))
 
-(defn measure-string [string]
+(defn measure-string
+  "CharSequenceMeasurement of number of characters and newlines in string"
+  [string]
   (measurement (count string) (count-matches \newline string)))
 
 (extend-type nil

  (charAt [this index] (nth this index))
  (length [this] (count this))
  (subSequence [this start end] (rope-subs this start end))
  (toString [this] (rope-str this))
  
  ;; ISeq
  ;; (first [_] left)
  ;; (more [this] (or (next this) (empty this)))
  ;; (next [this] (seq right))

  ;; Seqable
  ;; (seq [this] (when left this))

  ;; IPersistentCollection
  ;; (cons [this x] (rope x this))
  ;; (empty [_] (rope))
  ;; (equiv [this x] (= (str this) (str x)))

  ;; ITransientCollection
  ;; (conj [this x] (println "called") (rope-conj this x))
  ;; (persistent [this] this)
  )

(defmethod print-method Rope [rope writer]
  (print-simple (format "#<Rope %s>" (->> (measure rope) vals (join "/"))) writer))

            (recur (cons current acc) (next coll) (fib-border length)))
          (fold acc))))))

(defmulti rope-concat
  "Concatenation of two Ropes, including Strings which are treated as leafes"
  (fn [rope1 rope2] [(type rope1) (type rope2)]))
(defmethod rope-concat [String String] [string1 string2] (str string1 string2))
(defmethod rope-concat :default [coll1 coll2]
  (let [new-rope (rope coll1 coll2)]
