(ns auto-ap.views.pages.data-page
  (:require
   [auto-ap.status :as status]
   [auto-ap.subs :as subs]
   [auto-ap.utils :refer [deep-merge replace-by]]
   [auto-ap.views.utils :as u]
   [re-frame.core :as re-frame]))

(re-frame/reg-sub
 ::checked
 (fn [db [_ id]]
   (get-in db [::checked id] {})))

(re-frame/reg-event-db
 ::toggle-check
 (fn [db [_ id new]]
   (assoc-in db [::checked id] new)))

(re-frame/reg-event-db
 ::remove-check
 (fn [db [_ id to-remove]]
   (update-in db
              [::checked id]
              (fn [checked]
                (let [checked (or checked {})]
                  (dissoc checked to-remove))))))

(re-frame/reg-sub
 ::checked-set
 (fn [db [_ id]]
   (keys (get-in db [::checked id] {}))))

(re-frame/reg-event-db
 ::reset-checked
 (fn [db [_ id]]
   (update db ::checked dissoc id)))


(re-frame/reg-event-db
 ::updated-entity
 (fn [db [_ id entity]]
   (update-in db
              [::data id :data]
              replace-by :id (update entity :class #(or % "live-added")))))

(re-frame/reg-event-db
 ::deleted-entity
 (fn [db [_ id entity]]
   (update-in db
              [::data id :data]
              replace-by :id (update entity :class #(or % "live-removed")))))

(re-frame/reg-sub
 ::table-params
 (fn [db [_ which]]
   (get-in db [::table-params which])))

(re-frame/reg-sub
 ::additional-params
 (fn [db [_ which]]
   (get-in db [::additional-params which])))



(re-frame/reg-sub
 ::params
 (fn [[_ id]]
   [  #_(re-frame/subscribe [::subs/active-page])
    (re-frame/subscribe [::settled-filters id])
    (re-frame/subscribe [::table-params id])
    (re-frame/subscribe [::additional-params id])
    (re-frame/subscribe [::subs/selected-clients])])
 (fn [[filters table-params additional-params selected-clients]]
   (let [query-params (u/query-params)]
     (cond-> {:selected-clients selected-clients}
       (seq query-params)      (merge query-params)
       (seq filters)           (merge filters)
       (seq table-params)      (merge table-params)
       (seq additional-params) (merge additional-params)
       ))))

(re-frame/reg-event-fx
 ::received
 (fn [{:keys [db]} [_ id data]]
   (let [uri-params (dissoc @(re-frame/subscribe [::params id]) :selected-clients)
         current-uri-params (u/query-params)]
     (cond-> {:db (-> db (assoc-in [::data id] data)
                      (assoc :query-params uri-params))}
       (not= uri-params current-uri-params) (assoc :set-uri-params uri-params)))))

(re-frame/reg-event-db
 ::dispose
 (fn [db [_ id]]
   (-> db
       (update ::data dissoc id)
       (update ::checked dissoc id)
       (update ::table-params dissoc id)
       (update ::filters dissoc id)
       (update ::settled-filters dissoc id))))

(defn dispose-all [db]
  (-> db
      (dissoc ::data ::checked ::table-params ::filters ::settled-filters)))


(re-frame/reg-sub
 ::data
 (fn [db [_ id]]
   (get-in db [::data id])))

(re-frame/reg-sub
 ::page
 (fn [[_ id]]
   [(re-frame/subscribe [::data id])
    (re-frame/subscribe [::status/single [::page id]])
    (re-frame/subscribe [::checked id])
    (re-frame/subscribe [::checked-set id])
    (re-frame/subscribe [::params id])
    (re-frame/subscribe [::table-params id])
    (re-frame/subscribe [::filters id])])
 (fn [[data status checked checked-set params table-params filters] [_ id]]
   {:id id
    :data data
    :status status
    :checked checked
    :checked-set checked-set
    :params params
    :filters filters 
    :table-params table-params}))

(re-frame/reg-event-fx
 ::table-params-changed
 (fn [{:keys [db]} [_ which params]]
   {:db (update-in db [::table-params which] merge params)}))


(re-frame/reg-event-fx
 ::additional-params-changed
 (fn [{:keys [db]} [_ which params]]
   {:db (-> db
            (update-in [::additional-params which] merge params)
            (assoc-in [::table-params which :start] 0))}))

(re-frame/reg-sub
 ::specific-filters
 (fn [db [_ id]]
   (get-in db [::filters id])))

(re-frame/reg-sub
 ::filters
 (fn [[_ id]]
   [(re-frame/subscribe [::specific-filters id])
    (re-frame/subscribe [::subs/query-params])])
 (fn [[specific-filters query-params] ]
   (deep-merge query-params (or specific-filters {}) )))

(re-frame/reg-sub
 ::filter
 (fn [[_ id]]
   [(re-frame/subscribe [::filters id])])
 (fn [[filters] [_ _ which]]
   (get filters which)))


(re-frame/reg-event-fx
 ::filters-settled
 (fn [{:keys [db]} [_ id]]
   {:db (-> db
            (assoc-in [::settled-filters id] @(re-frame/subscribe [::filters id]))
            (assoc-in [::table-params id :start] 0))}))

(re-frame/reg-sub
 ::settled-filters
 (fn [db [_ id]]
   (get-in db [::settled-filters id])))

(re-frame/reg-event-fx
 ::filter-changed
 (fn [{:keys [db]} [_ id & params]]
   (let [[a b c] params
         [which val] (if (= 3 (count params))
                       [(into [a] b) c]
                       [[a] b])]
     {:db (-> db
              (assoc-in (into [::filters id] which) val))
      :dispatch-debounce
      {:event [::filters-settled id]
       :time 800
       :key [::filters id]}})))
