                  (butlast)
                  vec))))
 
-(defn parent [state]
+(defn parent-state [state]
   (let [{:keys [state-index]} state]
     (get state-index (parent-id state))))
+
+(defn select-event-transitions [state event]
+  (concat (->> (state-transitions state)
+               (filter #(= (trigger-event %) event)))
+          (lazy-seq (if-some [parent (parent-state state)]
+                      (select-event-transitions parent event)))))
+
+(defn select-eventless-transitions [state]
+  (concat (->> (state-transitions state)
+               (filter #(nil? (trigger-event %))))
+          (lazy-seq (if-some [parent (parent-state state)]
+                      (select-eventless-transitions parent)))))
 
 (defn state-zip [state]
   (zip/zipper
     (constantly true)
     substates
     (fn [state] (prn "edit"))
-    state
-    ))
-
-(defn make-transitions [state]
-  (let [{:keys [id]} state]
-    (update state :transitions
-            (fn [transitions]
-              (->> transitions
-                   (map (fn [transition]
-                          (let [{:keys [target]} transition]
-                            (cond-> transition
-                              (keyword? target)
-                              (assoc :target (conj id target)))))))))))
-
-
+    state))
+
+(defn make-transitions [state state-index]
+  (let [{:keys [id transitions]} state]
+    (cond-> state
+            (some? transitions)
+            (update :transitions
+                    (fn [transitions]
+                      (->> transitions
+                           (mapv (fn [transition]
+                                   (let [{:keys [target]} transition]
+                                     (cond-> (assoc transition
+                                               :source id
+                                               :state-index state-index)
+                                             (keyword? target)
+                                             (assoc :target (conj id target))))))))))))
 
 (defn index-states [state]
   (loop [loc (state-zip state)

                                  :target :home}
                                 {:event  :goto-betting
                                  :target :betting}]
                   }}}))
(ns sc-demo-page.statechart1
  (:require [clojure.zip :as zip]
            [clojure.set :as set]))

(defprotocol State
  (initialize-statechart [this])
  (initial-states [this])
  (substates [this])
  (state-id [this])
  (state-type [this])
  (state-transitions [this])
  (entry-order [this])
  (on-exit [this])
  (on-enter [this])
  (get-state [this id]))

(defprotocol Transition
  (trigger-event [this])
  (target-state [this])
  (source-state [this])
  (internal? [this])
  (on-trigger [this])
  (applicable-transition? [this ctx]))

(defn compound? [state]
  (= (state-type state) :xor))

(defn component? [state]
  (= (state-type state) :and))

(defn atomic? [state]
  (not (or (compound? state)
           (component? state))))


(defn current-event [ctx]
  (:current-event ctx))

(defn current-event-id [ctx]
  (first (current-event ctx)))

(defn pop-event [ctx]
  (let [event (-> ctx :internal-queue peek)]
    (-> ctx
        (assoc :current-event event)
        (update :internal-queue pop))))

(defn make-ctx [configuration fx event]
  {:configuration  (->> configuration
                        (filter atomic?)
                        (into #{}))
   :internal-queue (conj clojure.lang.PersistentQueue/EMPTY event)
   :fx             fx})

(extend-type
  clojure.lang.PersistentArrayMap

  Transition
  (trigger-event [this]
    (:event this))
  (target-state [this]
    (get-state this (:target this)))
  (source-state [this]
    (get-state this (:source this)))
  (internal? [this]
    (:internal this false))
  (on-trigger [this]
    (:execute this))
  (applicable-transition? [this ctx]
    (let [event-id       (current-event-id ctx)
          {:keys [condition]} this
          trigger-event' (trigger-event this)]
      (and (or (nil? trigger-event')
               (= event-id trigger-event'))
           (or (nil? condition)
               (condition ctx)))))

  State
  (initialize-statechart [this]
    (case (:type this)
      :and
      (mapcat initialize-statechart (vals (:states this)))

      :xor
      (initialize-statechart (get-in this [:states (:init this)]))

      [this]))
  (initial-states [this]
    (case (:type this)
      :xor
      (list (get-in this [:states (:init this)]))

      :and
      (vals (:states this))

      (list)))
  (substates [this]
    (vals (:states this)))
  (state-id [this]
    (:id this))
  (state-type [this]
    (:type this))
  (state-transitions [this]
    (:transitions this))
  (entry-order [this]
    (:order this))
  (on-exit [this]
    (:exit this))
  (on-enter [this]
    (:enter this))
  (get-state [this id]
    (get (:state-index this) id)))

(defn targetted-transition? [transition]
  (some? (target-state transition)))

(defn parent-id [state]
  (let [id (state-id state)]
