(ns buddho.core.state.protocols
  (:require [buddho.core.state.memory :refer [state]]))

(defprotocol Idea
  (fn-liberal [idea fn]
    "Apply function `fn` to `idea`,
accepting both identifiers and values for the latter;
mind that keys are functions.")
  (reference [idea] "Reference, i.e. symbol, for `idea`.")
  (value [idea] "Value, i.e. map, of `idea`."))

(extend-protocol Idea
  cljs.core/PersistentHashMap
  (fn-liberal [dhamma fn]
    (fn dhamma))
  (reference [idea] (:_reference idea))
  (value [idea] idea)

  cljs.core/PersistentArrayMap
  (fn-liberal [dhamma fn]
    (fn dhamma))
  (reference [idea] (:_reference idea))
  (value [idea] idea)

  Symbol
  (fn-liberal [idea fn]
    (fn-liberal (value idea) fn))
  (reference [idea] idea)
  (value [idea] (get @state idea)))

;; TODO better error handling
(defn copy [idea] (assoc (value idea) :_reference nil))

(defn apply-fn [fn idea] (fn-liberal idea fn))

(def value-safe (fnil value {}))
