(ns auto-ap.views.components.layouts
  (:require
   [auto-ap.events :as events]
   [auto-ap.permissions :as p]
   [auto-ap.forms :as forms]
   [auto-ap.forms.builder :as form-builder]
   [auto-ap.routes :as routes]
   [auto-ap.ssr-routes :as ssr-routes]
   [auto-ap.routes.payments :as payment-routes]
   [auto-ap.routes.invoice :as invoice-routes]
   [auto-ap.subs :as subs]
   [auto-ap.views.components.modal :as modal]
   [auto-ap.views.components.search :as search]
   [auto-ap.views.components.vendor-dialog :as vendor-dialog]
   [auto-ap.views.utils
    :refer [active-when appearing dispatch-event-with-propagation login-url]]
   [bidi.bidi :as bidi]
   [clojure.string :as str]
   [re-frame.core :as re-frame]
   [reagent.core :as r]
   [vimsical.re-frame.cofx.inject :as inject]))

(defn navbar-drop-down [{:keys [ class]} _]
  (let [!child (r/atom nil)]
    (r/create-class
      {:reagent-render (fn [{:keys [header id]} child]
                         (let [menu-active? @(re-frame/subscribe [::subs/menu-active? id])]
                           [:div { :class    (str "navbar-item has-dropdown " (when menu-active? "is-active " ) " " class)
                                  :ref   (fn [n]
                                           (reset! !child n))
                                  :tab-index 0
                                  :onBlur    (fn [_]
                                            (js/setTimeout (fn []
                                                             (println @!child)
                                                             (println (.-activeElement js/document))
                                                             (when-not (.contains @!child (.-activeElement js/document))
                                                               (re-frame/dispatch [::events/toggle-menu id])))
                                                           2))}
                            [:a {:class "navbar-link login" :on-click (fn [e]
                                                                        (.preventDefault e)
                                                                        (.stopPropagation e)
                                                                        (re-frame/dispatch [::events/toggle-menu id])
                                                                        true)} header]
                            [appearing {:visible? menu-active? :enter-class "appear" :exit-class "disappear" :timeout 200}
                             [:div {:class "navbar-dropdown"}
                              [:div child]]]]))})))

(defn login-dropdown []
  (let [user (re-frame/subscribe [::subs/user])]
    (if @user
      [navbar-drop-down {:header [:span [:span.icon [:i.fa.fa-user]]
                                  [:span (:user/name @user)]]
                         :id     ::account}
       [:div
        (when (p/can? @user {:subject :my-company-page})
          [:a {:class "navbar-item"
               :href  (bidi/path-for auto-ap.ssr-routes/only-routes :company)} "My company"])
        (when (p/can? @user {:subject :vendor
                             :activity :create})
          [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::vendor-dialog/started {}])} "New Vendor"])
        
        (when (p/can? @user {:subject  :vendor
                             :activity :edit})
          [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::vendor-dialog/edit {}])} "Edit Vendor"])
        (when (p/can? @user {:subject :admin-page})
          [:a {:class "navbar-item" :href (bidi/path-for ssr-routes/only-routes :auto-ap.routes.admin/page)} "Administration"])
        (when (not= "read-only" (:user/role @user))
          [:hr {:class "navbar-divider"}])
        [:a.navbar-item {:on-click (fn []
                                     (.removeItem js/localStorage "last-client-id" nil)
                                     (.setItem js/localStorage "last-selected-clients" ":all")
                                     (.reload (.-location js/document ) true))}
         "Full Refresh"]
        [:a.navbar-item {:on-click (fn [e] (.preventDefault e) (re-frame/dispatch [::events/logout]))} "Logout"]]]
      [:a.navbar-item {:href (login-url)} "Login"])))

(re-frame/reg-sub
 ::client-search
 (fn [db]
   (::client-search db)))

(re-frame/reg-sub
 ::matching-clients
 :<- [::subs/clients]
 :<- [::forms/form ::client-search]
 (fn [[clients {{client-search :value} :data}]]
   (if (empty? client-search) 
     clients
     (if-let [exact-match (first (filter
                                  (fn [client]
                                    (= (str/lower-case (or (:code client) "INVALID")) (str/lower-case client-search)))
                                  clients))]
       [exact-match]
       (filter
        (fn [client]
          (or 
           (str/includes? (str/lower-case (or (:code client) "INVALID")) (str/lower-case client-search))
           (str/includes? (str/lower-case (:name client)) (str/lower-case client-search))))
        clients)))))


(re-frame/reg-event-fx
  ::client-searched
  [(re-frame/inject-cofx ::inject/sub [::matching-clients])]
  (fn [{::keys [matching-clients]}]
    {:dispatch-n [[::events/swap-client (first matching-clients)]
                  [::events/toggle-menu ::select-client]]}))

(defn client-dropdown []
  (let [client           (re-frame/subscribe [::subs/client])
        clients @(re-frame/subscribe [::subs/selected-clients])
        selected-client-raw @(re-frame/subscribe [::subs/selected-clients-raw])
        matching-clients @(re-frame/subscribe [::matching-clients])
        user               (re-frame/subscribe [::subs/user])]
    
    [navbar-drop-down {:header (str "Company: " (cond @client
                                                      (:name @client)

                                                      (= :mine selected-client-raw)
                                                      "My Companies"

                                                      (= :all selected-client-raw)
                                                      "All Companies"

                                                      :else
                                                      (str (count (or clients [])) " Clients")))
                       :id ::select-client}
     [:div
      [:a {:class    "navbar-item"
           :on-click (fn []
                       (re-frame/dispatch [::events/toggle-menu ::select-client])
                       (re-frame/dispatch [::forms/form-closing ::client-search])
                       (re-frame/dispatch [::events/swap-client :all]))} "All" ]
      (when (= "admin" (:user/role @user))
        [:a {:class    "navbar-item"
             :on-click (fn []
                         (re-frame/dispatch [::events/toggle-menu ::select-client])
                         (re-frame/dispatch [::forms/form-closing ::client-search])
                         (re-frame/dispatch [::events/swap-client :mine]))} "Mine" ])
      
      [:hr {:class "navbar-divider"}]
      [form-builder/builder {:id           ::client-search
                             :submit-event [::client-searched]}
       [form-builder/raw-field-v2  {:field :value}
        [:input.input.navbar-item {:placeholder "Company name"
                                   :auto-focus  true}]]]
      (for [{:keys [name id] :as client} (take 8 matching-clients)]
        ^{:key id }
        [:a {:class    "navbar-item"
             :on-click (fn []
                         (re-frame/dispatch-sync [::events/toggle-menu ::select-client])
                         (re-frame/dispatch-sync [::events/swap-client client]))
             } name])]]))

(defn navbar []
  (let [navbar-menu-shown? (r/atom false)]
    (fn [ap]
      (let [user               (re-frame/subscribe [::subs/user])
            clients            (re-frame/subscribe [::subs/clients])
            is-initial-loading @(re-frame/subscribe [::subs/is-initial-loading?])]
        [:nav {:class "navbar has-shadow is-fixed-top is-grey"}
         [:div {:class "container"}
          [:div {:class "navbar-brand"}
           [:a {:class "navbar-item", :href "../"}
            [:img {:src "/img/logo.png"}]]
           [:div {:class "navbar-burger burger", :data-target "navMenu" :on-click (fn [] (swap! navbar-menu-shown? #(not %)))}
            [:span]
            [:span]
            [:span]]]
          [:div.navbar-menu {:id "navMenu" :class (if @navbar-menu-shown?
                                                    "is-active"
                                                    "")}
           (when-not is-initial-loading 
             [:div.navbar-start
              [:a.navbar-item {:class [(active-when ap = :index)]
                               :href  (bidi/path-for routes/routes :index)}
               "Home" ]
              (when (p/can? @user {:subject :invoice-page})
                [:a.navbar-item {:class [(active-when ap #{:unpaid-invoices :paid-invoices})]
                                 :href  (str (bidi/path-for ssr-routes/only-routes ::invoice-routes/unpaid-page) "?date-range=year")}
                 "Invoices" ])
              (when (p/can? @user {:subject :payment-page})
                [:a.navbar-item {:class [(active-when ap = :payments)]
                                 :href  (str (bidi/path-for ssr-routes/only-routes ::payment-routes/all-page) "?date-range=month")}
                 "Payments" ])
              (when (p/can? @user {:subject :pos-page})
                [:a.navbar-item {:class [(active-when ap = :pos-sales)]
                                 :href  (str (bidi/path-for ssr-routes/only-routes :pos-sales) "?date-range=week")}
                 "POS" ])
              (when (p/can? @user {:subject :transaction-page})
                [:a.navbar-item {:class [(active-when ap = :transactions)]
                                 :href  (bidi/path-for routes/routes :transactions)}
                 "Transactions" ])
              (when (p/can? @user {:subject :ledger-page})
                [:a.navbar-item {:class [(active-when ap = :ledger)]
                                 :href (bidi/path-for routes/routes :ledger)}
                 "Ledger" ])])
           (when-not is-initial-loading
             [:div.navbar-end
              (when (> (count @clients) 1)
                [client-dropdown])
              ])]
          (when-not is-initial-loading
            [login-dropdown])]
         (when (= "admin" (:user/role @user))
           [:div {:style {:position "fixed" :top "4px" :right "8px"}}
            [search/search-button  ]])]))))


(defn appearing-side-bar [{:keys [visible?]} ]
  [appearing {:visible? visible? :enter-class "slide-in-right" :exit-class "slide-out-right" :timeout 500}
   [:aside  {:class "column is-4 aside menu" :style {:height "calc(100vh - 46px)" :overflow "auto"}}
    (into [:div.sub-main {} ]
          (r/children (r/current-component)))]])

(defn side-bar-layout [{:keys [side-bar main bottom right-side-bar]}]
  (let [ap @(re-frame/subscribe [::subs/active-page])
        client @(re-frame/subscribe [::subs/client])]
    [:div 
     [modal/global-modal]
     [navbar ap]
     
     [:div {:class "columns has-shadow", :style {:margin-bottom "0px" :height "calc(100vh - 46px)" } :id "mail-app" }
      [:aside {:class "column aside menu is-2 " }
       [:div.main.left-nav 
        [:div side-bar
         ]]]
      [:div {:class "column messages hero " :style { :overflow "auto" }, :id "message-feed"}
       ^{:key (str "active-page-" (:name client))}
       [:div.inbox-messages
        (when-let [error  @(re-frame/subscribe [::subs/page-failure])]
          [:div.notification.is-warning.animated.fadeInUp
           error])
        main]]
      (when right-side-bar
        right-side-bar)
      ]
     [:div 
      bottom]
     [:div#dz-hidden]]))


(defn side-bar [{:keys [on-close]} children]
  [:div [:a.delete.is-pulled-right {:on-click on-close}] [:div children]])

(defn loading-layout []
  [side-bar-layout 
   {:main [:div.has-text-centered.hero.is-fullheight.is-vertically-centered.is-centered 
           [:div.hero-body
            [:div.container 
             [:div.column.is-4.is-offset-4.has-text-centered
              [:div.loader.is-loading.is-active.big.is-centered]]]]]}])

