(ns companion
  (:require [reagent.core :as r]))

(defonce timer-id (atom nil))

(defn get-random-item [categories filter-categories]
  (let [filtered-cats (if (empty? filter-categories)
                        categories
                        (filter #(contains? filter-categories (:id %)) categories))
        all-items (mapcat :items filtered-cats)]
    (when (seq all-items)
      (nth all-items (rand-int (count all-items))))))

(defn start-timer! [state]
  (when @timer-id
    (js/clearInterval @timer-id))
  (let [interval @(r/cursor state [:companion :interval])
        pick-new-item (fn []
                        (let [categories @(r/cursor state [:categories])
                              filter-cats @(r/cursor state [:companion :filter-categories])
                              item (get-random-item categories filter-cats)]
                          (swap! state assoc-in [:companion :current-item] item)))]
    (pick-new-item)
    (reset! timer-id (js/setInterval pick-new-item interval))
    (swap! state assoc-in [:companion :running?] true)))

(defn stop-timer! [state]
  (when @timer-id
    (js/clearInterval @timer-id)
    (reset! timer-id nil))
  (swap! state assoc-in [:companion :running?] false))

(defn toggle-timer! [state]
  (if @(r/cursor state [:companion :running?])
    (stop-timer! state)
    (start-timer! state)))

(defn next-item! [state]
  (let [categories @(r/cursor state [:categories])
        filter-cats @(r/cursor state [:companion :filter-categories])
        item (get-random-item categories filter-cats)]
    (swap! state assoc-in [:companion :current-item] item)
    (when @(r/cursor state [:companion :running?])
      (start-timer! state))))

(defn arg-display [arg]
  [:span.companion-arg
   [:strong (:name arg)] " : " (:type arg)
   (when (:range arg)
     [:span " (" (:range arg) ")"])])

(defn prompt-display [item]
  [:div.prompt-display
   (if item
     [:<>
      [:div.prompt-name
       (or (:name item) (:symbol item))]
      (when-let [sig (:signature item)]
        [:div.prompt-signature sig])
      [:div.prompt-description (:description item)]
      (when-let [args (:args item)]
        [:div.prompt-args
         (for [[idx arg] (map-indexed vector args)]
           ^{:key idx}
           [arg-display arg])])
      (when-let [example (:example item)]
        [:pre.prompt-example example])]
     [:div.prompt-empty "Press play to start"])])

(defn interval-button [state interval-ms label]
  (let [current @(r/cursor state [:companion :interval])]
    [:button.interval-btn
     {:class (when (= current interval-ms) "selected")
      :on-click (fn []
                  (swap! state assoc-in [:companion :interval] interval-ms)
                  (when @(r/cursor state [:companion :running?])
                    (start-timer! state)))}
     label]))

(defn category-filter [state]
  (let [categories @(r/cursor state [:categories])
        filter-cats @(r/cursor state [:companion :filter-categories])]
    [:div.category-filter
     [:span.filter-label "Focus: "]
     [:button.filter-btn
      {:class (when (empty? filter-cats) "selected")
       :on-click #(swap! state assoc-in [:companion :filter-categories] #{})}
      "All"]
     (for [cat categories]
       ^{:key (:id cat)}
       [:button.filter-btn
        {:class (when (contains? filter-cats (:id cat)) "selected")
         :on-click (fn []
                     (swap! state update-in [:companion :filter-categories]
                            (fn [cats]
                              (if (contains? cats (:id cat))
                                (disj cats (:id cat))
                                (conj (or cats #{}) (:id cat))))))}
        (:name cat)])]))

(defn companion-view [state]
  (let [running? @(r/cursor state [:companion :running?])
        current-item @(r/cursor state [:companion :current-item])]
    [:div.companion
     [:div.companion-main
      [prompt-display current-item]]
     [:div.companion-controls
      [:div.playback-controls
       [:button.play-btn
        {:on-click #(toggle-timer! state)}
        (if running? "Pause" "Play")]
       [:button.next-btn
        {:on-click #(next-item! state)}
        "Next"]]
      [:div.interval-controls
       [interval-button state 5000 "5s"]
       [interval-button state 10000 "10s"]
       [interval-button state 30000 "30s"]
       [interval-button state 60000 "60s"]]
      [category-filter state]]]))
