(ns frontend.components.find-in-page
  (:require [rum.core :as rum]
            [frontend.ui :as ui]
            [frontend.state :as state]
            [frontend.util :as util]
            [frontend.handler.search :as search-handler :refer [debounced-search, stop-debounced-search!]]
            [goog.object :as gobj]
            [goog.dom :as gdom]
            [frontend.mixins :as mixins]
            [clojure.string :as string]))

(rum/defc search-input
  [q matches]
  (let [*composing? (rum/use-ref false)
        on-change-fn (fn [e]
                       (let [value (util/evalue e)
                             e-type (gobj/getValueByKeys e "type")]
                         (state/set-state! [:ui/find-in-page :q] value)
                         (cond (= e-type "compositionstart")
                               (do (rum/set-ref! *composing? true)
                                   (stop-debounced-search!))

                               (= e-type "compositionend")
                               (rum/set-ref! *composing? false))
                         (when-not (rum/deref *composing?)
                           (debounced-search))))]
    [:div.flex.w-48.relative
     [:input#search-in-page-input.form-input.block.sm:text-sm.sm:leading-5.my-2.border-none.mr-4.outline-none
      {:auto-focus true
       :placeholder "Find in page"
       :aria-label "Find in page"
       :value q
       :on-composition-start on-change-fn
       :on-composition-end on-change-fn
       :on-change on-change-fn}]
     (when-not (string/blank? q)
       (when-let [total (:matches matches)]
         [:div.text-sm.absolute.top-2.right-0.py-2.px-4
          (:activeMatchOrdinal matches 0)
          "/"
          total]))
     [:div#search-in-page-placeholder.absolute.top-2.left-0.p-2.sm:text-sm]]))

(rum/defc search-inner < rum/static
  (mixins/event-mixin
   (fn [state]
     (mixins/hide-when-esc-or-outside
      state
      :node (gdom/getElement "search-in-page")
      :on-hide (fn []
                 (search-handler/electron-exit-find-in-page!)))))
  [{:keys [matches match-case? q]}]
  [:div#search-in-page.flex.flex-row.absolute.top-10.right-4.shadow-lg.px-2.py-1.faster.fade-in.items-center

   (search-input q matches)

   (ui/button
    (ui/icon "letter-case")
    :on-click (fn []
                (state/update-state! [:ui/find-in-page :match-case?] not)
                (debounced-search))
    :intent "link"
    :small? true
    :title "Match case"
    :class (str (when match-case? "active ") "text-lg"))

   (ui/button
    (ui/icon "caret-up")
    :on-click (fn []
                (state/set-state! [:ui/find-in-page :backward?] true)
                (debounced-search))
    :intent "link"
    :small? true
    :class "text-lg"
    :title "Previous result")

   (ui/button
    (ui/icon "caret-down")
    :on-click (fn []
                (state/set-state! [:ui/find-in-page :backward?] false)
                (debounced-search))
    :intent "link"
    :small? true
    :class "text-lg"
    :title "Next result")

   (ui/button
    (ui/icon "x")
    :on-click (fn []
                (search-handler/electron-exit-find-in-page!))
    :intent "link"
    :small? true
    :class "text-lg"
    :title "Close")])

(rum/defc search < rum/reactive
  []
  (let [{:keys [active?] :as opt} (state/sub :ui/find-in-page)]
    (when active?
      (search-inner opt))))
