 
 (declare get entity)
 
+(defn p-nil?
+  "Return true if value is nil or '_"
+  [x]
+  (or (nil? x) (= '_ x)))
+
 (defn pattern->idx
   "Returns type of listener pattern."
-  [pattern]
-  (let [[id attr val] (mapv #(if (= % '_) nil %) pattern)]
-    (cond (and id attr) :entity-attr
-          (and attr val) :attr-val
-          id :id
-          attr :attr
-          :else nil)))
+  [[e a v :as x]]
+  (let [pattern (keyword (str (if (p-nil? e) "_" "e")
+                              (if (p-nil? a) "_" "a")
+                              (if (p-nil? v) "_" "v")))]
+    (when-not (#{:e__ :ea_ :_av :_a_} pattern)
+      (println {:pattern pattern :x x})
+      (throw (js/Error. (str "Unsupported pattern: " " " pattern "e: " e "a: " a "v: " v))))
+    pattern))
+
+;; spec
+
 
 (defn- pattern->listener-path
   "Returns path to listener set for the given access pattern."
   [[id attr val :as pattern]]
   (case (pattern->idx pattern)
-    :entity-attr [:listeners :entity-attr id attr]
-    :attr-val [:listeners :attr-val attr val]
-    :id [:listeners :entity id]
-    :attr [:listeners :attr attr]
+    :e__ [:listeners :e__ id]
+    :ea_ [:listeners :ea_ id attr]
+    :_av [:listeners :_av attr val]
+    :_a_ [:listeners :_a_ attr]
     nil [:listeners :tx-log]))
 
 (declare listen! unlisten!)

    (fn [db-snap attr val]
      (let [schema (get-schema db-snap attr)
            prev-val (get* prev-m attr)]
        (if (many? schema)
          (update-index db-snap id attr
                        (set/difference val prev-val)
                        (set/difference prev-val val)
                        schema)
          (update-index db-snap id attr val prev-val schema))))
    db-snap m))

(defn add-map-datoms [datoms id m prev-m db-snap]

  "Returns entity for resolved id."
  [db-snap id]
  (when-let [id (resolve-id db-snap id)]
    (log-read [:e__] conj [id])
    (some-> (get-in* db-snap [:eav id])
            (assoc id-attr id))))

