 (ns todomvc.events
   (:require
-    [todomvc.db    :refer [default-db todos->local-store]]
+    [todomvc.db :refer [default-db todos->local-store]]
     [re-frame.core :refer [reg-event-db reg-event-fx inject-cofx path after]]
     [cljs.spec.alpha :as s]
     [day8.re-frame.tracing :refer-macros [fn-traced]]))

;; To fully understand this advanced topic, you'll have to read the tutorials
;; and look at the bottom of `db.cljs` for the `:local-store-todos` cofx
;; registration.
(reg-event-fx                 ;; part of the re-frame API
  :initialise-db              ;; event id being handled

  ;; the interceptor chain (a vector of 2 interceptors in this case)
  [(inject-cofx :local-store-todos) ;; gets todos from localstore, and puts value into coeffects arg
   check-spec-interceptor]          ;; after event handler runs, check app-db for correctness. Does it still match Spec?

  ;; the event handler (function) being registered
  (fn [{:keys [db local-store-todos]} _]                  ;; take 2 values from coeffects. Ignore event vector itself.
    {:db (assoc default-db :todos local-store-todos)}))   ;; all hail the new state to be put in app-db


;; usage:  (dispatch [:set-showing  :active])
;; This event is dispatched when the user clicks on one of the 3
;; filter buttons at the bottom of the display.
(reg-event-db      ;; part of the re-frame API
  :set-showing     ;; event-id

  ;; only one interceptor
  [check-spec-interceptor]       ;; after event handler runs, check app-db for correctness. Does it still match Spec?

  ;; handler
  (fn [db [_ new-filter-kw]]     ;; new-filter-kw is one of :all, :active or :done
    (assoc db :showing new-filter-kw)))

;; NOTE: below is a rewrite of the event handler (above) using a `path` Interceptor

  :toggle-done
  todo-interceptors
  (fn-traced [todos [_ id]]
             (update-in todos [id :done] not)))


(reg-event-db
  :save
  todo-interceptors
  (fn-traced [todos [_ id title]]
             (assoc-in todos [id :title] title)))


(reg-event-db
  :delete-todo
  todo-interceptors
  (fn-traced [todos [_ id]]
             (dissoc todos id)))


(reg-event-db
  :clear-completed
  todo-interceptors
  (fn-traced [todos _]
             (let [done-ids (->> (vals todos)               ;; which todos have a :done of true
                                 (filter :done)
                                 (map :id))]
               (reduce dissoc todos done-ids))))            ;; delete todos which are done


(reg-event-db
  :complete-all-toggle
  todo-interceptors
  (fn-traced [todos _]
             (let [new-done (not-every? :done (vals todos))] ;; work out: toggle true or false?
               (reduce #(assoc-in %1 [%2 :done] new-done)
                       todos
                       (keys todos)))))
