;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC Sucursal en España SL

(ns app.main.ui.ds.controls.switch
  (:require-macros
   [app.main.style :as stl])
  (:require
   [app.common.data :as d]
   [app.util.dom :as dom]
   [app.util.keyboard :as kbd]
   [cuerdas.core :as str]
   [rumext.v2 :as mf]))

(def ^:private schema:switch
  [:map
   [:class {:optional true} :string]
   [:label {:optional true} [:maybe :string]]
   [:aria-label {:optional true} [:maybe :string]]
   [:default-checked {:optional true} [:maybe :boolean]]
   [:on-change {:optional true} [:maybe fn?]]
   [:disabled {:optional true} :boolean]])

(mf/defc switch*
  {::mf/schema schema:switch}
  [{:keys [class label aria-label default-checked on-change disabled] :rest props} ref]
  (let [checked*   (mf/use-state default-checked)
        checked?   (deref checked*)

        id   (mf/use-id)

        disabled?  (d/nilv disabled false)

        has-label? (not (str/blank? label))

        handle-toggle
        (mf/use-fn
         (mf/deps on-change checked? disabled?)
         #(when-not disabled?
            (let [updated-checked? (not checked?)]
              (reset! checked* updated-checked?)
              (when on-change
                (on-change updated-checked?)))))

        handle-keydown
        (mf/use-fn
         (mf/deps handle-toggle)
         (fn [event]
           (dom/prevent-default event)
           (when-not disabled?
             (when (or (kbd/space? event) (kbd/enter? event))
               (handle-toggle event)))))

        props
        (mf/spread-props props {:ref ref
                                :role "switch"
                                :aria-label (when-not has-label?
                                              aria-label)
                                :class [class (stl/css-case :switch true
                                                            :off (false? checked?)
                                                            :neutral (nil? checked?)
                                                            :on (true? checked?))]
                                :aria-checked checked?
                                :tab-index (if disabled? -1 0)
                                :on-click handle-toggle
                                :on-key-down handle-keydown
                                :disabled disabled?})]

    (mf/use-effect
     (mf/deps default-checked)
     (fn []
       (reset! checked* default-checked)))

    [:> :div props
     [:div {:id id
            :class (stl/css :switch-track)}
      [:div {:class (stl/css :switch-thumb)}]]
     (when has-label?
       [:label {:for id
                :class (stl/css :switch-label)}
        label])]))
