(ns buddho.core.describe
  (:require [clojure.string :as string]
            [buddho.core.state.memory :refer [state]]
            [buddho.core.state.protocols :refer [value value-safe]]
            [buddho.core.dhamma.aspects :as asp]
            [buddho.core.state.property :as prop]))

(defn describe-property! [property description & [fun]]
  (swap! state assoc-in [:_descriptions :property property] description)
  (when fun
    (swap! state assoc-in [:_descriptions :property-fn property] fun)))

(defn describe-dhamma! [dh-kw description]
  (swap! state assoc-in [:_descriptions :dhamma dh-kw] description))

(defn prop-desc [prop & [idea]]
  (let [desc (get-in @state [:_descriptions :property prop])]

    (if-let [fun (get-in @state [:_descriptions :property-fn prop])]
      (str desc "\n" (fun idea))
      desc)))

(defn dh-desc [dh-kw]
  (get-in @state [:_descriptions :dhamma dh-kw]))

(defn description-of [property & [idea]]
  (loop [prop property
         ctx {}]
    (let [desc (prop-desc prop idea)]
      (if-not (seq prop)
        ctx
        (recur (vec (butlast prop)) (assoc ctx prop desc))))))

(defn description [idea]
  (->> (prop/properties idea)
       (map #(description-of % idea))
       (apply merge)))

(defn describe [idea]
  (doseq [[prop desc] (description idea)]
    (println prop "=>" desc)))

(defn descr-dhamma-fn [idea]
  ;;; TODO things this is an aspect of
  (let [idea (value-safe idea)
        aspects (asp/aspects-of idea)
        format-singleton #(if (prop/has-property? % [:dhamma :singleton]) "{S} " "{T} ")
        format-dh
        (fn [dh] (str "<" (format-singleton dh)
                      (:name (value dh)) " "
                      dh ">"))
        asp-strs (map (fn [[prop dhs]]
                        (str prop
                             " -> "
                             (#(if (empty? %1) %2 %1)
                              (string/join ", " (map format-dh dhs))
                              "(none)")))
                      aspects)]
    (str
     "Name:\t\t" (:name idea) "\n"
     (dh-desc (:name idea)) "\n"
     "Aspects:\t" (string/join "\n\t\t\t" asp-strs) "\n"
     "Data:\t\t" (:data idea) "\n"
     "Meta:\t\t" (:meta idea) "\n"
     "Transient?:\t" (:transient idea)
     )))

(describe-property! [:dhamma] "Idea is a dhamma." descr-dhamma-fn)
