;; 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.utilities.token-field
  (:require-macros [app.main.style :as stl])
  (:require
   [app.common.data :as d]
   [app.common.data.macros :as dm]
   [app.main.refs :as refs]
   [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
   [app.main.ui.ds.foundations.assets.icon :as i]
   [app.main.ui.ds.tooltip :refer [tooltip*]]
   [app.util.dom :as dom]
   [app.util.i18n :refer [tr]]
   [rumext.v2 :as mf]))


(def ^:private schema:token-field
  [:map
   [:class {:optional true} [:maybe :string]]
   [:id {:optional true} [:maybe :string]]
   [:label {:optional true} [:maybe :string]]
   [:property {:optional true} [:maybe :string]]
   [:value :any]
   [:disabled {:optional true} :boolean]
   [:is-open {:optional true} :boolean]
   [:slot-start {:optional true} [:maybe some?]]
   [:on-click {:optional true} fn?]
   [:on-token-key-down fn?]
   [:on-blur {:optional true} fn?]
   [:on-focus {:optional true} fn?]
   [:tooltip-placement {:optional true}
    [:maybe [:enum "top" "bottom" "left" "right" "top-right" "bottom-right" "bottom-left" "top-left"]]]
   [:detach-token fn?]])

(mf/defc token-field*
  {::mf/schema schema:token-field}
  [{:keys [id label value slot-start disabled class
           on-click on-token-key-down on-blur detach-token tooltip-placement
           token-wrapper-ref token-detach-btn-ref on-focus property is-open
           token-has-errors]}]
  (let [set-active? (some? id)

        all-tokens-map (mf/deref refs/workspace-all-tokens-map)
        token-exists? (contains? all-tokens-map label)
        token-not-active (and token-exists? (not set-active?))
        content (cond
                  (not token-exists?)
                  (tr "options.deleted-token-with-name" label)

                  (and token-exists? (not set-active?))
                  (tr "ds.inputs.token-field.no-active-token-option" label)

                  (and token-exists? token-has-errors)
                  (tr "workspace.tokens.ref-not-valid" label)

                  :else
                  label)

        broken-state (or (not token-exists?)
                         token-has-errors
                         token-not-active)

        default-id  (mf/use-id)
        id          (d/nilv id default-id)
        pill-ref    (mf/use-ref nil)

        focus-wrapper
        (mf/use-fn
         (mf/deps disabled)
         (fn [event]
           (when-not ^boolean disabled
             (dom/prevent-default event)
             (dom/focus! (mf/ref-val token-wrapper-ref)))))]
    [:> tooltip* {:content property
                  :class (stl/css :token-field-wrapper)
                  :trigger-ref token-wrapper-ref
                  :id (dm/str default-id "-input")}
     [:div {:class [class (stl/css-case :token-field true
                                        :with-icon (some? slot-start)
                                        :token-field-disabled disabled)]
            :on-click focus-wrapper
            :disabled disabled
            :on-key-down on-token-key-down
            :ref token-wrapper-ref
            :on-blur on-blur
            :on-focus on-focus
            :aria-labelledby (dm/str default-id "-input")
            :tab-index (if disabled -1 0)}

      (when (some? slot-start) slot-start)

      [:div  {:class (stl/css :content-wrapper)}
       [:> tooltip* {:content content
                     :trigger-ref pill-ref
                     :id (dm/str id "-pill")}
        [:button {:on-click on-click
                  :ref pill-ref
                  :class (stl/css-case :pill true
                                       :no-set-pill broken-state
                                       :pill-disabled disabled)
                  :disabled disabled
                  :aria-labelledby (dm/str id "-pill")
                  :on-key-down on-token-key-down}
         value
         (when broken-state
           [:div {:class (stl/css :pill-dot)}])]]]

      (when-not ^boolean disabled
        [:> icon-button* {:variant "ghost"
                          :class (stl/css-case :invisible-button true
                                               :invisible-btn-dropdown-open is-open)
                          :tooltip-class (stl/css :button-tooltip)
                          :tooltip-placement tooltip-placement
                          :icon i/broken-link
                          :ref token-detach-btn-ref
                          :aria-label (tr "token-actions.detach-token")
                          :on-click detach-token}])]]))
