;; 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.inspect.right-sidebar
  (:require-macros [app.main.style :as stl])
  (:require
   [app.common.types.component :as ctk]
   [app.config :as cf]
   [app.main.data.event :as ev]
   [app.main.refs :as refs]
   [app.main.store :as st]
   [app.main.ui.ds.buttons.button :refer [button*]]
   [app.main.ui.ds.controls.select :refer [select*]]
   [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
   [app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
   [app.main.ui.ds.product.empty-state :refer [empty-state*]]
   [app.main.ui.inspect.attributes :refer [attributes*]]
   [app.main.ui.inspect.code :refer [code*]]
   [app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
   [app.main.ui.inspect.styles :refer [styles-tab*]]
   [app.util.dom :as dom]
   [app.util.i18n :refer [tr]]
   [app.util.shape-icon :as usi]
   [rumext.v2 :as mf]))

(defn- get-libraries
  "Retrieve all libraries, including the local file, on workspace or viewer"
  [from]
  (if (= from :workspace)
    (deref refs/libraries)
    (let [viewer-data (deref refs/viewer-data)
          local       (get-in viewer-data [:file :data])
          id          (get local :id)
          libraries   (:libraries viewer-data)]
      (-> libraries
          (assoc id {:id id
                     :data local})))))

(mf/defc right-sidebar*
  [{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
    :or {from :viewer}}]
  (let [color-space*   (mf/use-state "hex")
        color-space    (deref color-space*)

        section        (mf/use-state #(if (contains? cf/flags :inspect-styles) :styles :info))
        objects        (or objects (:objects page))
        shapes         (or shapes
                           (resolve-shapes objects selected))
        first-shape    (first shapes)
        page-id        (or page-id (:id page))
        file-id        (or file-id (:id file))

        libraries      (get-libraries from)
        main-instance? (ctk/main-instance? first-shape)

        subtitle       (cond
                         (or
                          (ctk/is-variant-container? first-shape)
                          (and (not (ctk/is-variant? first-shape)) main-instance?))
                         (tr "inspect.subtitle.main")
                         (and (ctk/is-variant? first-shape) main-instance?)
                         (tr "labels.variant")
                         (ctk/instance-head? first-shape)
                         (tr "inspect.subtitle.copy"))

        handle-change-tab
        (mf/use-fn
         (mf/deps from on-change-section)
         (fn [new-section]
           (reset! section (keyword new-section))
           (when on-change-section
             (on-change-section (keyword new-section))
             (st/emit!
              (ev/event {::ev/name "change-inspect-tab" :tab new-section})))))

        handle-expand
        (mf/use-fn
         (mf/deps on-expand)
         (fn []
           (when on-expand (on-expand))))

        navigate-to-help
        (mf/use-fn
         (fn []
           (dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))

        handle-change-color-space
        (mf/use-fn
         (fn [color-space]
           (reset! color-space* color-space)))

        color-spaces
        (mf/with-memo []
          [{:label (tr "inspect.attributes.color.hex")
            :id "hex"}
           {:label (tr "inspect.attributes.color.rgba")
            :id "rgba"}
           {:label (tr "inspect.attributes.color.hsla")
            :id "hsla"}])

        tabs
        (mf/with-memo []
          (if (contains? cf/flags :inspect-styles)
            [{:label (tr "labels.styles")
              :id "styles"}
             {:label (tr "labels.computed")
              :id "computed"}
             {:label (tr "labels.code")
              :data-testid "code"
              :id "code"}]
            [{:label (tr "labels.info")
              :id "info"}
             {:label (tr "labels.code")
              :data-testid "code"
              :id "code"}]))]

    (mf/use-effect
     (mf/deps shapes handle-change-tab)
     (fn []
       (if (seq shapes)
         (st/emit! (ev/event {::ev/name "inspect-mode-click-element"}))
         (handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info)))))

    [:aside {:class (stl/css-case :settings-bar-right true
                                  :viewer-code (= from :viewer))}
     (if (seq shapes)
       [:div {:class (stl/css :tool-windows)}
        [:div {:class (stl/css-case :shape-info true :shape-info-subtitle (some? subtitle))}
         (if (> (count shapes) 1)
           [:*
            [:div {:class (stl/css :layers-icon)}
             [:> icon* {:icon-id i/layers :size "s"}]]
            [:span {:class (stl/css :layer-title)} (tr "inspect.multiple-selected" (count shapes))]]
           [:*
            [:div {:class (stl/css :shape-icon)}
             ;; Use the shape icon utility to get the correct icon for the first shape
             [:> icon* {:icon-id (usi/get-shape-icon first-shape) :size "s"}]]
            ;; Execution time translation strings:
            ;;   (tr "inspect.tabs.code.selected.circle")
            ;;   (tr "inspect.tabs.code.selected.component")
            ;;   (tr "inspect.tabs.code.selected.curve")
            ;;   (tr "inspect.tabs.code.selected.frame")
            ;;   (tr "inspect.tabs.code.selected.group")
            ;;   (tr "inspect.tabs.code.selected.image")
            ;;   (tr "inspect.tabs.code.selected.mask")
            ;;   (tr "inspect.tabs.code.selected.path")
            ;;   (tr "inspect.tabs.code.selected.rect")
            ;;   (tr "inspect.tabs.code.selected.svg-raw")
            ;;   (tr "inspect.tabs.code.selected.text")

            [:div
             (if (some? subtitle)
               [:*
                [:div {:class (stl/css :layer-title :layer-title-with-subtitle)} (:name first-shape)]
                [:div {:class (stl/css :layer-subtitle)} subtitle]]
               [:div
                [:div {:class (stl/css :layer-title)} (:name first-shape)]])]])]

        [:div {:class (stl/css :inspect-content)}
         (if (contains? cf/flags :inspect-styles)
           [:div {:class (stl/css :inspect-tab-switcher)}
            [:span {:class (stl/css :inspect-tab-switcher-label)} (tr "inspect.layer-info")]
            [:div {:class (stl/css :inspect-tab-switcher-controls)}
             [:div {:class (stl/css :inspect-tab-switcher-controls-color-space)}
              [:> select* {:class (stl/css :inspect-tab-switcher-controls-color-space-select)
                           :aria-label (tr "inspect.color-space-label")
                           :options color-spaces
                           :default-selected "hex"
                           :variant "ghost"
                           :on-change handle-change-color-space}]]
             [:div {:class (stl/css :inspect-tab-switcher-controls-tab)}
              [:> select* {:options tabs
                           :aria-label (tr "inspect.tabs-switcher-label")
                           :default-selected (name @section)
                           :on-change handle-change-tab}]]]]
           nil)

         (if (contains? cf/flags :inspect-styles)
           [:div {:class (stl/css :inspect-tab :viewer-tab-switcher :viewer-tab-switcher-layout)}
            (case @section
              :styles
              [:> styles-tab* {:color-space color-space
                               :objects objects
                               :shapes shapes
                               :from from
                               :libraries libraries
                               :page-id page-id
                               :file-id file-id
                               :share-id share-id}]
              :computed
              [:> attributes* {:color-space color-space
                               :page-id page-id
                               :objects objects
                               :file-id file-id
                               :frame frame
                               :shapes shapes
                               :from from
                               :libraries libraries
                               :share-id share-id}]

              :code
              [:> code* {:frame frame
                         :shapes shapes
                         :on-expand handle-expand
                         :from from}])]
           [:> tab-switcher* {:tabs tabs
                              :selected (name @section)
                              :on-change handle-change-tab
                              :class (stl/css :viewer-tab-switcher)}
            (case @section
              :info
              [:> attributes* {:page-id page-id
                               :objects objects
                               :file-id file-id
                               :frame frame
                               :shapes shapes
                               :from from
                               :libraries libraries
                               :share-id share-id}]

              :code
              [:> code* {:frame frame
                         :shapes shapes
                         :on-expand handle-expand
                         :from from}])])]]

       [:*
        [:div {:class (stl/css :empty)}
         [:> empty-state* {:icon i/code
                           :text (tr "inspect.empty.select")}]
         [:> empty-state* {:icon i/help
                           :text (tr "inspect.empty.help")}]]
        [:div {:class (stl/css :empty-button)}
         [:> button* {:variant "secondary"
                      :on-click navigate-to-help}
          (tr "inspect.empty.more")]]])]))
