(ns auto-ap.ssr.components.buttons
  (:require [auto-ap.ssr.svg :as svg]
            [auto-ap.ssr.hiccup-helper :as hh]))

(defn button-icon- [_ i]
  [:div.h-4.w-4 i])

(defn bg-colors [color disabled]
  (let [base-color (cond (= :primary color)
                         "green"
                         (= :secondary color)
                         "blue"

                         (= :red color)
                         "red"

                         (nil? color)
                         "white"

                         (sequential? color)
                         (first color)

                         :else
                         color)
        base-weight (or (when (sequential? color)
                          (second color))
                        500)
        disabled-weight (when disabled 400)]

    (format " bg-%s-%d hover:bg-%s-%d  focus:ring-%s-%d dark:bg-%s-%d dark:hover:bg-%s-%d "
            base-color
            (or disabled-weight (+ base-weight 0))

            base-color
            (or disabled-weight (+ base-weight 100))

            base-color
            (or disabled-weight (int (* base-weight 0.5)))

            base-color
            (or disabled-weight (+ base-weight 100))

            base-color
            (or disabled-weight (+ base-weight 200)))))

(defn dark-color-weight [disabled]
  (if disabled
    400
    600))

(defn hover-color-weight [disabled]
  (if disabled
    400
    600))

(for [color ["green" "blue" "white"]
      weight (range 100 900 100)]
  (str "bg-" color "-" weight))
;;ensuring these colors show up
;; => ("bg-green-100"
;;     "bg-green-200"
;;     "bg-green-300"
;;     "bg-green-400"
;;     "bg-green-500"
;;     "bg-green-600"
;;     "bg-green-700"
;;     "bg-green-800"
;;     "bg-blue-100"
;;     "bg-blue-200"
;;     "bg-blue-300"
;;     "bg-blue-400"
;;     "bg-blue-500"
;;     "bg-blue-600"
;;     "bg-blue-700"
;;     "bg-blue-800"
;;     "bg-white-100"
;;     "bg-white-200"
;;     "bg-white-300"
;;     "bg-white-400"
;;     "bg-white-500"
;;     "bg-white-600"
;;     "bg-white-700"
;;     "bg-white-800")

(defn button- [params & children]

  [:button (update params
                   :class #(cond-> %
                             true (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center relative justify-center  disabled:opacity-50"
                                       (bg-colors  (:color params) (:disabled params)))

                             (not (:disabled params))
                             (str " hover:scale-105 transition duration-100")

                             (:disabled params)
                             (str " cursor-not-allowed")

                             (not (nil? (:color params)))
                             (str " text-white ")

                             (nil? (:color params))
                             (str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700")))
   [:div.htmx-indicator.flex.items-center.absolute.inset-0.justify-center
    (svg/spinner {:class "inline w-4 h-4 text-white"})
    (when (not (:minimal-loading? params))
      [:div.ml-3 "Loading..."])]
   (into [:div.htmx-indicator-invisible.inline-flex.gap-2.items-center.justify-center] children)])

(defn a-button- [params & children]
  [:a (-> params
          (update :class #(cond-> %
                            true                           (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center hover:scale-105 transition duration-100 justify-center")
                            (= :secondary (:color params)) (str " text-white  bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700")
                            (= :primary (:color params))   (str " text-white bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ")
                            (= :secondary-light (:color params))   (str " text-blue-800 bg-white-200 border-gray-100 border hover:bg-blue-100 focus:ring-blue-100 dark:bg-blue-400 dark:hover:bg-blue-800 ")
                            (nil? (:color params))
                            (str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700")))
          (assoc :tabindex 0)
          (assoc :href (:href params "#")))
   (when (:indicator? params true)
     [:div.htmx-indicator.flex.items-center
      (svg/spinner {:class "inline w-4 h-4 text-white"})
      [:div.ml-3 "Loading..."]])
   (into [:div.inline-flex.gap-2.items-center.justify-center {:class (when (:indicator? params true)
                                                                                             "htmx-indicator-hidden")}] 
         children)])

(defn icon-button- [params & children]
  (into
   [:button

    (update params :class
            #(cond-> %
               true (str " inline-flex items-center justify-center items-center p-3 text-sm font-medium border border-gray-300 dark:border-gray-700 text-center rounded-lg hover:scale-110")
               (= :secondary (:color params)) (str " bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700")
               (= :primary (:color params))   (str " bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ")
               (= :primary-light (:color params))   (str " bg-green-200 hover:bg-green-300 focus:ring-green-200 dark:bg-green-700 dark:hover:bg-green-600 text-gray-800 dark:text-gray-200")
               (= :secondary-light (:color params))   (str " bg-blue-200 hover:bg-blue-300 focus:ring-blue-200 dark:bg-blue-700 dark:hover:bg-blue-600 text-gray-800 dark:text-gray-200")
               (= :danger-light (:color params))   (str " bg-red-200 hover:bg-red-300 focus:ring-red-200 dark:bg-red-700 dark:hover:bg-red-600 text-gray-800 dark:text-gray-200")
               (nil? (:color params))
               (str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100")))
    [:div.htmx-indicator.flex.items-center
     (svg/spinner {:class "inline w-4 h-4 text-white"})]
    [:div.htmx-indicator-hidden.inline-flex.gap-2.items-center.justify-center (into [:div.h-4.w-4] children)]]))

(defn a-icon-button- [params & children]
  (let [class-str (:class params "")
        has-padding? (re-find #"\bp[x y]?-\d+(\.\d+)?\b" class-str)]
    (into
     [:a (-> params (update :class str (if has-padding? "" " p-3") " inline-flex items-center justify-center bg-white dark:bg-gray-600 items-center text-sm font-medium border border-gray-300 dark:border-gray-700 text-center text-gray-500 hover:text-gray-800 rounded-lg dark:text-gray-400 dark:hover:text-gray-100")
             (update :href #(or % "")))
      [:div.h-4.w-4 children]])))

(defn save-button- [params & children]
  [:button {:class "text-white bg-green-500 hover:bg-green-700 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800 inline-flex items-center hover:scale-105 transition duration-300"}
   [:div.htmx-indicator.flex.items-center
    (svg/spinner {:class "inline w-4 h-4 text-white"})
    [:div.ml-3 "Loading..."]]
   (into [:div.htmx-indicator-hidden] children)])



(defn group-button- [{:keys [size] :or {size :normal} :as params} & children]
  (into [:button (cond-> params
                   true (assoc :type (or (:type params) "button"))
                   true (update :class (fn [c]
                                         (cond-> c
                                           true (str " font-medium text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-2 focus:ring-green-700 focus:text-green-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-green-500 dark:focus:text-white")

                                           (= :small size)
                                           (str " text-xs px-3 py-2")

                                           (= :normal size)
                                           (str " text-sm px-4 py-2"))))
                   true (dissoc :size))] children))

(defn group- [{:keys [name]} & children]
  (let [children (-> children
                     vec
                     (update-in [0 1 :class] str " rounded-l-lg")
                     (update-in [(dec (count children)) 1 :class] str " rounded-r-lg"))]
    (into [:div {:class "inline-flex rounded-md shadow-sm", :role "group"
                 :hx-on:click "this.querySelector(\"input\").value = event.target.value; this.querySelector(\"input\").dispatchEvent(new Event('change', {bubbles: true}));"}
           [:input {:type "hidden" :name name}]]
          children)))

(defn navigation-button- [{:keys [class next-arrow?] :or {next-arrow? true} :as params} & children]
  [:button
   (-> params
       (update :class (fnil hh/add-class  "") 
               "p-4 text-green-700 border border-gray-300 rounded-lg bg-gray-50 
                dark:bg-gray-800 dark:border-green-800 dark:text-green-400 
                focus:ring-green-400 focus:ring-2 
                hover:border-green-300 hover:bg-green-200 hover:dark:bg-gray-800 hover:dark:border-green-800 
                hover:dark:text-green-400")
       (dissoc :next-arrow?))
   [:div
    {:class "flex items-center justify-between"}
    [:span {:class "sr-only"} children]
    [:h3 {:class "font-medium"} children]
    (when next-arrow?
      [:div.w-4.h-4
       svg/arrow-right])]])

(defn navigation-button-list- [{:keys []} & children]
  [:ol
   {:class "space-y-4 w-72"}
   (for [n children]
     [:li n])
   
   #_[:li
      [:div
       {:class
        "w-full p-4 text-gray-900 bg-gray-100 border border-gray-300 rounded-lg dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400",
        :role "alert"}
       [:div
        {:class "flex items-center justify-between"}
        [:span {:class "sr-only"} "Review"]
        [:h3 {:class "font-medium"} "4. Review"]]]]
   #_[:li
      [:div
       {:class
        "w-full p-4 text-gray-900 bg-gray-100 border border-gray-300 rounded-lg dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400",
        :role "alert"}
       [:div
        {:class "flex items-center justify-between"}
        [:span {:class "sr-only"} "Confirmation"]
        [:h3 {:class "font-medium"} "5. Confirmation"]]]]])


(defn validated-save-button- [{:keys [errors class] :as params} & children]
  (button- (-> {:color (or (:color params) :primary)
                :type  "submit" :class (cond-> (or class "")
                                         true (hh/add-class "w-32")
                                         (seq errors) (hh/add-class "animate-shake"))}
               (merge (dissoc params :class))
               (dissoc :errors))
           (if (seq children)
             children
             "Save")))
