     [clojure.spec :as s]
     [merkle-db.key :as key]))
 
+
+;; ## Record Keys
 
 ;; Count of the records contained under a node.
 (s/def ::count nat-int?)

    #(= (reduce + (map count (vals %)))
        (count (distinct (apply concat (vals %)))))))



;; ## Family Functions

(defn- family-lookup
  "Build a lookup function for field families. Takes a map from family keys to

        updates
        (family-groups families data)))
    {} records))



;; ## Updating Functions

(defn field-merger
  "Construct a new record updating function from the given merge spec. The
  resulting function accepts three arguments, the record id, the existing
  record data (or nil), and the new record data map.

  If the merge spec is a function, it will be called with
  `(f field-key old-val new-val)` for each field in the record and the
  field-key will be set to the resulting value.

  If the merge spec is a map, the keys will be used to look up a merge function
  for each field in the record, which will be called with `(f old-val new-val)`.
  If a field has no entry in the spec, the new value is always used."
  [spec]
  {:pre [(or (fn? spec) (map? spec))]}
  (let [merger (if (map? spec)
                 (fn merger
                   [fk l r]
                   (if-let [f (get spec fk)]
                     (f l r)
                     r))
                 spec)]
    (fn merge-fields
      [id old-data new-data]
      (reduce
        (fn [data field-key]
          (let [left (get old-data field-key)
                right (get new-data field-key)
                value (merger field-key left right)]
            (assoc data field-key value)))
        (empty old-data)
        (distinct (concat (keys old-data) (keys new-data)))))))
