(ns yaml-table.core
  (:require [cljs.nodejs :as node]
            [cljs.core.async :refer [buffer offer! poll! close! take! put! chan <! >! alts!]]
            [yaml-table.config :as config])
  (:require-macros [cljs.core.async.macros :refer [go go-loop]]))

(node/enable-util-print!)

(defn string->num-yaml-docs [s]
  ;(println "Clojure + Python")
  (count (re-seq #"---\n" s)) ; hacky for now
  #_(min
   ;;(.match s /^---$/gm)
   ;(.match s /^...$/gm) 
   (count (re-seq #"^---\n" s))
   ;(count (re-seq #"\n...$" s))
  ))

(defn file-path->string-with-contents [path]
  (let [fs (node/require "fs")]
    (.readFileSync fs path "utf8")
    ))

(defn string->yaml-object-chan [string]
  (let
    [yaml (node/require "js-yaml") 
      fs (node/require "fs") 
      n (string->num-yaml-docs string)
      c (chan n)]
      (.safeLoadAll 
        yaml
        string 
        (fn [returned-yaml-object] 
          (go 
            (>! c returned-yaml-object)
            (if (= n (count (.-buf c)))
              (close! c)))))
    c))

(defn fill-vector-from-chan [c]
  (into [] [(go <! c)]))

(def not-nil? (complement nil?))

; QWERTY
(defn vector-with-channels->channel-with-array [vwc]
  (let [c (chan 1)]
    (go-loop [ov vwc tv []]
      (if (empty? ov)
        (>! c (clj->js tv))
        (let [[v p] (alts! ov)]
          (recur (vec (if (= (count (.-buf p)) 0) (remove #{p} ov) ov)) (conj tv v)))) ; stick function here
          ;(recur (vec (remove #{p} ov)) (conj tv v))))
    ) c ))


;
(defn chan-table-package->table [yaml-config-chan arr-chan rows days]
  (let 
    [res (node/require "../resources/print-yaml-table.js")]
    (go 
(.printYamlTable res (<! yaml-config-chan) (<! arr-chan) rows days))))

(defn path->chan-vec-ext-strings [path ext]
  (let [c (chan 1) dir (node/require "node-dir")]
    (.files dir path (fn [err files] 
                               (go (>! c (js->clj (.filter files (fn [file] (.endsWith file ext)))))))
    ) 
    c ))

(defn -main [& args]
  (let [minimist         (node/require "minimist")
        argv             (minimist (clj->js (vec args)))
	ext              (or (.-e argv) "yaml")
	path             (or (aget (aget argv "_") 0) "$HOME") ;□ >1 paths; default path
	table-name       (or (aget argv "n") "default") ;□ >1 paths; default path
        rows             (or (js/parseInt (.-r argv)) 10)
        days             (or (js/parseInt (.-d argv)) 1000000)
        yaml-config-chan (config/yaml-table-config->chan-matching-yaml-object table-name)
	chan-vec-filenames               (path->chan-vec-ext-strings path ext)
        file-path->chan-yaml               (comp string->yaml-object-chan file-path->string-with-contents)
        ]

    (go 
      (let [vec-chan-yamls (mapv file-path->chan-yaml (<! chan-vec-filenames))
            arr-chan (vector-with-channels->channel-with-array vec-chan-yamls)]
        (chan-table-package->table yaml-config-chan arr-chan rows days)))))

(set! *main-cli-fn* -main)
