(ns sekai.event.subscriber
  (:require [sekai.core.gamestate :refer [game-state]]))

(defn make-subscriber [type predicate & [target-m data-m cascades-m]]
  { :id (gensym "subscriber_")
    :type type
    :predicate predicate
    :target-m (or target-m identity)
    :data-m (or data-m identity)
    :cascades-m (or cascades-m identity) })

(defn register-subscriber! [sub]
  (swap! game-state update-in [:subscribers (:type sub)] (fnil conj []) sub))

(defn get-subscribers [event]
  (let [subs (get-in @game-state [:subscribers (:type event)])]
    (filter #((:predicate %) event) subs)))

(defn apply-subscriber [event sub]
  (-> event
       (update-in [:targets] (:target-m sub))
       (update-in [:data] (:data-m sub))
       (update-in [:cascades] (:cascades-m sub))))

(defn process-subscribers [event]
  (let [subs (get-subscribers event)]
    (reduce #(apply-subscriber %1 %2) event subs)))
