(ns sekai.event.event
  (:require [sekai.entity.selector :as selector]
            [sekai.util.util :as util]
            [sekai.event.subscriber :as subscriber]
            [sekai.event.queue :as queue]
            [sekai.core.gamestate :refer [game-state]]))

(defn make-event [type source targets data cascades]
  { :id (gensym "event_")
    :type type
    :source source
    :targets targets
    :data data
    :cascades cascades })

(defmulti dispatch! :type)

(defn do-event!
  "Execute `event`, applying listeners and handling cascades."
  [event]
  (let [[queue cascade]
    (-> event
        (update :targets (partial util/map-values selector/gather))
        subscriber/process-subscribers
        dispatch!)]
    (run! queue/enqueue! queue)
    (run! do-event! cascade)))

(defn process-tick! [tick]
  (let [queue (get-in @game-state [:queue tick])]
    (run! do-event! queue)
    (swap! game-state assoc-in [:queue tick] nil)))
