(ns bigml-nodered-core.wz.units
  (:require clojure.string
            [bigml-nodered-core.wz.marshal :as marshal]))

;; building blocks
(defn wz-def [name body]
  (str "(define " name " " body ")"))

(defn wz-defn [name pars body]
  (wz-def name (str " (lambda (" (clojure.string/join " " pars) ") " body ")")))

(defn wz-merge [m1 m2]
  (str "(merge " m1 " " m2 ")"))

(defn wz-latest [t & [q]]
  (let [q (or q {})
        l (or (get q "limit") 1)
        q (marshal/wz-marshal-map (assoc q "limit" l))]
    (if (or (= l 1) (= l "1"))
      (str "(head (resource-ids (resources " t " " q ")))")
      (str "(resource-ids (resources " t " " q "))"))))

(defn wz-create [t opts]
  (str "(create-and-wait \"" t "\" " (marshal/wz-marshal-map opts) ")"))

(defn wz-map-get [map key]
  (str "(get " map " " key ")"))

(defn wz-fetch [rid out-key opts]
  (let [map (str "(fetch " rid " " (marshal/wz-marshal-map opts) ")")]
    (if (nil? out-key)
      map
      (wz-map-get map out-key))))

(defn wz-random-split [d & [r n1 n2]]
  (let [r (or r 0.8)
        nn1 (str (or n1 "Dataset") " - Training")
        nn2 (str (or n2 n1 "Dataset") " - Test")]
    (str "(create-random-dataset-split " d " " r
               " { \"name\" \"" nn1 "\"}"
               " { \"name\" \"" nn2 "\"})")))

(defn wz-get-keypath [m k ins]
  (if (clojure.string/includes? k ".")
    (let [cs (clojure.string/split k #"\.")]
      (str "(get-in r " (marshal/wz-marshal-list cs true) ")"))
    (str "(if (contains? " m " \"" k "\") (get r \"" k "\") "
         (if (contains? ins k)
           (marshal/wz-marshal (get ins k))
           (str "(raise \"Missing required input: " k "\")") )
         " )")))
