               :gt [(.max js/Math (+ rhs (/ time-unit 16)) min-t) Infinity]))))
 
 (defn transition-interval [has ha transition]
-  #_(println "Transition" (:id ha) (:x ha) (:target transition) (:guard transition))
+  #_(println "Transition" (:id ha) "et" (:entry-time ha) (:target transition) (:guard transition))
   (let [intervals (map #(simple-interval has ha %) (:guard transition))
         interval (intersect-all intervals)]
     #_(println "interval:" intervals "->" interval)

                                         ha
                                         Infinity
                                         (required-transitions ha)))
        #_(println "New required transitions" (transition-intervals has
                                                                    ha
                                                                    Infinity
                                                                    (required-transitions ha)))

(def time-unit (/ frame-length time-units-per-frame))
(def precision 0.001)

(defn simple? [i]
  (if-let [[imin imax] i]
    (and (number? imin) (number? imax))
    false))

(defn empty-interval? [i]
  (if (simple? i)
    (> (first i) (second i))
    (every? empty-interval? i)))

(declare merge-overlapping)

(defn intersection [a b]
  (cond
    (or (empty-interval? a) (empty-interval? b)) [Infinity Infinity]
    (and (simple? a) (simple? b)) (let [[amin amax] a
                                        [bmin bmax] b]
                                    (cond
                                      (< bmin amin) (intersection b a)
                                      (< amax bmin) nil
                                      :else [(.max js/Math amin bmin) (.min js/Math amax bmax)]))
    ; b (resp. a) is a disjunction of simple intervals; intersect each with a (resp. b)
    (simple? a) (merge-overlapping (mapv #(intersection a %) b))
    (simple? b) (merge-overlapping (mapv #(intersection b %) a))
    ; both are disjunctions of simple intervals. union of intersections
    ; (a1 u a2 u a3) ^ (b1 u b2 u b3) == (a1 ^ b1 u a1 ^ b2 u a1 ^ b3) u ...
    :else (merge-overlapping (vec
                               ; union of unions of pairwise intersections
                               (mapcat (fn [ai]
                                         ; union of pairwise intersections
                                         (mapv (fn [bi]
                                                 (intersection ai bi))
                                               b))
                                       a)))))

(defn sort-intervals [intervals]
  (sort (fn [a b]
          (cond
            (and (simple? a) (simple? b)) (compare (first a) (first b))
            (simple? a) (compare (first a) (ffirst b))
            (simple? b) (compare (ffirst a) (first b))
            :else (compare (ffirst a) (ffirst b))))
        intervals))

(defn flatten-intervals [intervals]
  (reduce (fn [sofar interval]
            (if (simple? interval)
              (conj sofar interval)
              (into sofar (flatten-intervals interval))))
          []
          intervals))

(defn merge-overlapping [intervals]
  (let [intervals (flatten-intervals intervals)
        intervals (sort-intervals intervals)
        [last-i merged] (reduce (fn [[[amin amax :as a] merged] [bmin bmax :as b]]
                                  (if (intersection a b)
                                    [[amin (.max js/Math amax bmax)] merged]
                                    [[bmin bmax] (conj merged a)]))
                                [(first intervals) []]
                                (rest intervals))]
    (if (empty? intervals)
      []
      (conj merged last-i))))

(defn constrain-times [interval]
  (if (simple? interval)
    [(ceil-time (first interval) time-unit) (floor-time (second interval) time-unit)]
    (mapv constrain-times interval)))

(defn intersect-all [intervals]
  (constrain-times
    (reduce (fn [a b]
              (if-let [intr (intersection a b)]
                intr
                [Infinity Infinity]))
            [time-unit Infinity]
            intervals)))

(defn union-all [intervals]
  (merge-overlapping intervals))

(defn third [v] (nth v 2))

