   (:require [bidi.router]
             [bidi.bidi :as bidi]
             [goog.events :as events]
+            [cats.labs.lens :as l]
+            [uxbox.state :as s]
             [uxbox.rstore :as rs]))
 
 (enable-console-print!)
 
-(def +router+ nil)
+(defonce +router+ (volatile! nil))
+
+(def ^:const route-l
+  (as-> (l/in [:route]) $
+    (l/focus-atom $ s/state)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Events


(defn go
  "Redirect the user to other url."
  ([name] (go name nil))
  ([name params] (rs/emit! (navigate name params))))

(defn route-for
  "Given a location handler and optional parameter map, return the URI
  for such handler and parameters."
  ([location]
   (bidi/path-for routes location))
  ([location params]
   (apply bidi/path-for routes location (into []
                                              (mapcat (fn [[k v]] [k v]))
                                              params))))

  (reify
    rs/UpdateEvent
    (-apply-update [_ state]
      (let [route (merge {:id handler}
                          (when route-params
                            {:params route-params}))]
        (assoc state :route route)))))

(defn navigate
  ([id] (navigate id nil))
  ([id params]
   {:pre [(keyword? id)]}
   (reify
     rs/EffectEvent
     (-apply-effect [_ state]
       (let [loc (merge {:handler id}
                        (when params
                          {:route-params params}))]
         (bidi.router/set-location! @+router+ loc))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Router declaration
