(ns auto-ap.ssr.form-cursor
  (:require [auto-ap.ssr.utils :refer [path->name2]]
            [auto-ap.cursor :as cursor]))

(def ^:dynamic *prefix* [])
(def ^:dynamic *form-data*)
(def ^:dynamic *form-errors*)
(def ^:dynamic *prev-cursor* nil)
(def ^:dynamic *current* nil)



(defmacro start-form [form-data errors & rest]
  `(binding [*form-data* ~form-data
             *form-errors* (or ~errors {})]
     (binding [*current* (if (cursor/cursor? *form-data*)
                           *form-data*
                           (cursor/cursor *form-data*))]
       ~@rest)))

(defmacro start-form-with-prefix [prefix form-data errors & rest]
  `(binding [*prefix* ~prefix]
     (start-form ~form-data ~errors ~@rest)))

(defmacro with-prefix [prefix & rest]
  `(binding [*prefix* (into (or *prefix* []) ~prefix)]
     ~@rest))

(defmacro with-cursor [cursor & rest]
  `(binding [*current* ~cursor]
     ~@rest))

(defmacro with-field [field & rest]
  `(with-cursor (get *current* ~field)
     ~@rest))

(defmacro with-field-default [field default & rest]
  `(let [new-cursor# (get *current* ~field  ~default)
         new-cursor2# (if (not (deref new-cursor#))
                       (do
                         (cursor/transact! *current*
                                           (fn [c#]
                                             (assoc c# ~field ~default)))
                         (get *current* ~field ~default))
  
                       new-cursor#)]
     (with-cursor new-cursor2#
       ~@rest)))

(defn field-name
  ([] (field-name *current*))
  ([cursor]
   (apply path->name2 (into (or *prefix* []) (cursor/path cursor)))))

(defn field-value
  ([] (field-value *current*))
  ([cursor] @cursor))

(defn field-errors
  ([]
   (println "CURRENT IS" *current*)
   (field-errors *current*))
  ([cursor]
   (get-in *form-errors* (cursor/path cursor))))

(defn error?
  ([]
   (error? *current*))
  ([cursor]
   (let [errors (get-in *form-errors* (cursor/path cursor))]
     (and (sequential? errors)
          (every? string? errors)))))


(defn cursor-map
  ([f] (cursor-map *current* f))
  ([cursor f]
   (when (seq (field-value))
     (doall
      (for [n cursor]
        (with-cursor n
          (f n)))))))


