          ::transition-count 0
          ::max-transitions max-transitions))
 
-(defn dispatch [{:keys [components] :as router} msg]
-  (when-let [component (peek (::component msg))]
-    (let [tunnel (get-tunnel router component)
-          dest (or tunnel component)
-          destcomp (get components dest)]
-      (cond (fn? destcomp)                   (destcomp msg)
-            (satisfies? ap/Channel destcomp) (a/put! destcomp msg)
-            (satisfies? p/Tunnel destcomp)   (p/send destcomp msg)
-            true (throw (ex-info "cannot dispatch" {:router router
-                                                    :msg msg
-                                                    :tunnel tunnel
-                                                    :component component
-                                                    :dest dest}))))))
+(defn make-router [ruleset components & {:keys [unit dispatch?]
+                                         :or {dispatch? true}}]
+  {:unit unit
+   :components components
+   :ruleset ruleset
+   :dispatch? dispatch?})
+
 
 #_(defn- process [this req]
   (advance req (:ruleset this)))

    (do (warn "dropping message due to high transition-count")
        [])))

(defn make-router [ruleset components & {:keys [unit dispatch?]
                                         :or {dispatch? true}}]
  {:unit unit
   :components components
   :ruleset ruleset
   :dispatch? dispatch?})

#_(defrecord MessageRouter [ruleset]

  p/Router

  (advance [this msg]
    (advance ruleset msg)))

#_(defn message-router [ruleset]
  (->MessageRouter ruleset))

(defn message [route map & {:keys [max-transitions]
                            :or {max-transitions 100}}]

(comment

  (def ruleset1
    {:units {:browser #{:input-validator :input-sanitizer}
             :server #{:auth-checker :booker :invoice-generator :notifier}}

     :routes {:book-flight
              {:transitions {nil :input-validator

                             :input-validator {:next :input-sanitizer}

                             :input-sanitizer {:next (fn [msg] :auth-checker)}

                             :auth-checker {:transform (fn [msg] (assoc msg :check #{:username :token}))
                                            :next :booker}

                             :booker {:next [:invoice-generator (fn [msg] :notifier)]}}}}})

  (def browser-components1 {:input-validator #(doto % (println "(input-validator)"))
                            :input-sanitizer #(doto % (println "(input-sanitizer)"))
                            :server #(doto % (println "(browser -> server)"))})

  (def server-components1 {:auth-checker #(doto % (println "(auth-checker)"))
                           :booker #(doto % (println "(booker)"))
                           :invoice-generator #(doto % (println "(invoice-generator)"))
                           ;;;:notifier #(doto % (println "(notifier)"))
                           :browser #(doto % (println "(server -> browser)"))
                           :DEFAULT #(doto % (println "(default)"))})

  (def browser-router1 (make-router ruleset1 browser-components1 :unit :browser))
  (def server-router1 (make-router ruleset1 server-components1 :unit :server))

  (def message1 (message :book-flight {:foo :bar}))

  (->> message1
       (route browser-router1)
       first
       (route browser-router1)
       first
       (route browser-router1)
       first
       (route server-router1)
       first
       (route server-router1)
       first
       (route server-router1))


  (dispatch {:unit :server
