 
 ;; -----------------------------------------------------------------------------
 ;; Event Handlers
+
+(defn on-env-animation-frame [timestamp]
+  (swap! state update-in [:env :frame-count] inc)
+  (get-in @state [:app :count-frames?]))
 
 (defn on-env-frames-per-second [fps]
   (swap! state assoc-in [:env :frames-per-second] fps)

   (let [[c1 c2 c3] (map #(:color %1) (keep #(get cells %1) (neighbors k)))]
     {:age 0 :color {:r (:r c1) :g (:g c2) :b (:b c3)}})))

(defn step [cells]
  (into {} (for [[k n] (->> (keys cells) (mapcat neighbors) (frequencies))
                 :let [cell (or (get cells k) (create-cell k cells))]
                 :when (or (= n 3) (and (= n 2) (contains? cells k)))]
             [k (update-in cell [:age] inc)])))


;; -----------------------------------------------------------------------------
;; Update / Render Cycle

(defn update! []
  (swap! state update-in [:gui :generation] inc))

(defn render! [timestamp state]
  (let [app-name (get-in state [:app :name])
        env-time (get-in state [:env :time])
        fps (get-in state [:env :frames-per-second])
        mouse-move (get-in state [:env :mouse-move])
        mouse-x (:client-x mouse-move)
        mouse-y (:client-y mouse-move)
        mouse-pos (str "[" mouse-x ":" mouse-y "]")
        gen (get-in state [:gui :generation])
        display [gen fps env-time timestamp mouse-pos]]
    (set! (.-innerText (app-div)) (string/join ", " display))))

(defn on-env-animation-frame [timestamp]
  (update!)
  (render! timestamp @state)
  (get-in @state [:app :rendering?]))

;; Event Subscriptions

(defn setup-event-subscriptions! []
  (swap! state assoc-in [:app :count-frames?] true)
  (poly/listen-animation-frame! on-env-animation-frame)
  (swap! state assoc-in [:app :measure-fps?] true)
  (poly/listen-fps! on-env-frames-per-second)
  (poly/take-back! (get-event-channel :env-keyboard-key) on-env-keyboard-key)
  (poly/take-back! (get-event-channel :env-mouse-move) on-env-mouse-move))

(defn teardown-event-subscriptions! []
  (swap! state assoc-in [:app :count-frames?] false)
  (swap! state assoc-in [:env :frame-count] 0))
  (swap! state assoc-in [:app :measure-fps?] false)
  (swap! state assoc-in [:env :frames-per-second] 0)


;; -----------------------------------------------------------------------------
