(ns wine-list
  "Regroups the wine list's rows by region, type or producer, and dates a printed list. The build writes the rows, the buttons, the group headings and the words around the date, so this script holds no strings of its own and is the same for every language.")

(def ^:private groupings #{"region" "type" "producer"})

(def ^:private table (js/document.querySelector ".wine-table"))

(def ^:private rows
  "The wine rows in the order the build wrote them, which every grouping keeps within its groups."
  (vec (.querySelectorAll table "tbody tr:not(.group-heading)")))

(def ^:private headings
  (.-content (js/document.querySelector "template.wine-group-headings")))

(def ^:private buttons
  (vec (js/document.querySelectorAll ".wine-grouping button")))

(defn- group-body
  "A row group of the table: the heading row `heading`, and the rows whose `grouping` is its key."
  [grouping heading]
  (let [k (.. heading -dataset -key)
        tbody (js/document.createElement "tbody")]
    (.add (.-classList tbody) "wine-group")
    (.append tbody (.cloneNode heading true))
    (doseq [row rows
            :when (= k (aget (.-dataset row) grouping))]
      (.append tbody row))
    tbody))

(defn- regroup!
  "Moves the rows into a group per value of `grouping`, in the order of the build's headings, and marks the button of the grouping as pressed."
  [grouping]
  (let [bodies (mapv (partial group-body grouping)
                     (.querySelectorAll headings (str "tr[data-group-by=\"" grouping "\"]")))]
    (doseq [tbody (vec (.querySelectorAll table "tbody"))]
      (.remove tbody))
    (doseq [tbody bodies]
      (.append table tbody))
    (set! (.. table -dataset -group) grouping)
    (doseq [button buttons]
      (.setAttribute button "aria-pressed" (str (= grouping (.. button -dataset -groupBy)))))))

(defn- switch-keeps!
  "Gives the language switch's link the ?group= of `grouping`, so the list in the other language opens grouped the same way."
  [grouping]
  (when-let [link (js/document.querySelector ".language-switch a")]
    (let [url (js/URL. (.getAttribute link "href") js/location.href)]
      (.set (.-searchParams url) "group" grouping)
      (.setAttribute link "href" (str (.-pathname url) (.-search url))))))

(defn- remember!
  "Keeps `grouping` in the URL as ?group=, so a link, a reload or the language switch keeps it."
  [grouping]
  (let [url (js/URL. js/location.href)]
    (.set (.-searchParams url) "group" grouping)
    (js/history.replaceState nil "" (str url)))
  (switch-keeps! grouping))

(defn- choose! [grouping]
  (regroup! grouping)
  (remember! grouping))

(defn- date-printout!
  "Dates a printed list with today, as the locale the build names on the date line writes a date, so paper says how current it is."
  []
  (when-let [printed (js/document.querySelector ".print-date")]
    (let [now (js/Date.)
          time-element (.querySelector printed "time")]
      (set! (.-dateTime time-element) (subs (.toISOString now) 0 10))
      (set! (.-textContent time-element) (.toLocaleDateString now (.. printed -dataset -locale) #js {:dateStyle "long"}))
      (set! (.-hidden printed) false))))

(doseq [button buttons]
  (.addEventListener button "click" #(choose! (.. button -dataset -groupBy))))

(let [grouping (.get (js/URLSearchParams. js/location.search) "group")]
  (when (groupings grouping)
    (switch-keeps! grouping)
    (when (not= grouping (.. table -dataset -group))
      (regroup! grouping))))

(date-printout!)
(js/addEventListener "beforeprint" date-printout!)

(set! (.-hidden (js/document.querySelector ".wine-grouping")) false)
