(ns uxbox.ui.lightbox
  (:require [sablono.core :as html :refer-macros [html]]
            [rum.core :as rum]
            [uxbox.ui.util :as util]
            [uxbox.ui.keyboard :as k]
            [goog.events :as events])
  (:import goog.events.EventType))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; State Management
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defonce +current+ (atom nil))

(defn open!
  ([kind]
   (open! kind nil))
  ([kind params]
   (reset! +current+ (merge {:name kind} params))))

(defn close!
  []
  (reset! +current+ nil))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; UI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defmulti render-lightbox :name)
(defmethod render-lightbox :default [_] nil)

(defn- on-esc-clicked
  [e]
  (when (k/esc? e)
    (close!)))

(defn- lightbox-will-mount
  [own]
  (let [key (events/listen js/document
                           EventType.KEYDOWN
                           on-esc-clicked)]
    (assoc own ::eventkey key)))

(defn- lightbox-will-umount
  [own]
  (let [key (::eventkey own)]
    (events/unlistenByKey key)
    (dissoc own ::eventkey)))

(defn- lightbox-transfer-state
  [old-own own]
  (assoc own ::eventkey (::eventkey old-own)))

(defn- lightbox-render
  [own]
  (let [params (rum/react +current+)]
    (html
     [:div.lightbox {:class (when (nil? params) "hide")}
      (render-lightbox params)])))

(def ^:static lightbox
  (util/component
   {:name "lightbox"
    :render lightbox-render
    :transfer-state lightbox-transfer-state
    :will-mount lightbox-will-mount
    :will-unmount lightbox-will-umount
    :mixins [rum/reactive]}))