(ns auto-ap.effects.forward
  (:require [re-frame.core :as re-frame]))

(def id->listen-fn (atom {}))

(re-frame/reg-fx
  ::register
  (let [process-one-entry (fn [{:as m :keys [id events event-fn]}]
                            (let [_ (assert (map? m) (str "re-frame: effects handler for :forward-events expected a map or a list of maps. Got: " m))
                                  _ (assert (= #{:id :events :event-fn} (-> m keys set)) (str "re-frame: effects handler for :forward-events given wrong map keys" (-> m keys set)))
                                  post-event-callback-fn (fn [event-v _]
                                                           (when (events (first event-v))
                                                             (re-frame/dispatch (event-fn event-v))))]
                              (re-frame/add-post-event-callback post-event-callback-fn)
                              (swap! id->listen-fn assoc id post-event-callback-fn)))]
    (fn [val]
      (cond
        (map? val)        (process-one-entry val)
        (sequential? val) (doall (map process-one-entry val))
        :else             (re-frame/console :error  ":forward-events expected a map or a list of maps, but got: " val)))))



(re-frame/reg-fx
  ::dispose
  (let [process-one-entry (fn [{:as m :keys [id]}]
                            (let [_ (assert (map? m) (str "re-frame: effects handler for :forward-events expected a map or a list of maps. Got: " m))
                                  _ (assert (= #{:id} (-> m keys set)) (str "re-frame: effects handler for :forward-events given wrong map keys" (-> m keys set)))
                                  f (@id->listen-fn id)
                                  _ (assert (some? f) (str ":forward-events  asked to unregister an unknown id: " id))]
                              (re-frame/remove-post-event-callback f)
                              (swap! id->listen-fn dissoc id)))]
    (fn [val]
      (cond
        (map? val)        (process-one-entry val)
        (sequential? val) (doall (map process-one-entry val))
        :else (re-frame/console :error  ":forward-events expected a map or a list of maps, but got: " val)))))
