(ns stone.eval
  (:require
   [wisp.runtime :refer [identity odd? even? dictionary? dictionary
                         keys vals key-values merge satisfies?
                         contains-vector? map-dictionary error?
                         string? number? date? boolean? re-pattern?
                         object? nil? true? false? re-find re-matches
                         re-pattern inc dec str char int subs and or
                         print to-string = max min fn? vector?]]
   [wisp.ast :refer [symbol symbol? keyword? keyword-name name
                     namespace gensym unquote? unquote-splicing?
                     quote? syntax-quote? quote-string pr-str
                     meta with-meta]]
   [wisp.sequence :refer [lazy-seq lazy-seq? list? list cons
                          sequential? reverse map filter reduce
                          count empty? first second third rest
                          last butlast take take-while drop conj
                          assoc concat seq seq? vec sort repeat
                          every? some partition interleave nth]]
   [wisp.string :refer [split split-lines join upper-case lower-case
                        capitalize pattern-escape replace-first replace
                        blank? reverse triml trimr trim]
                        :rename {reverse string-reverse}]
   [wisp.expander :refer [macroexpand]]
   [wisp.compiler :refer [evaluate compile]]
   [jsyaml]
   [stone.init :refer [zip find ->vec]]
   [Immutable :refer [List OrderedSet Map Seq]]
   ;;[Bluebird :refer [Promise]]
   [EthereumjsUtil]
   [jQuery :as $]))

(def emacs-connection nil)

(defn bind-eval
  [eval-func]
  (let [input ($ "#eval-expr")]
    (-> ($ input)
        (.on "keypress" (fn [e] (if (== (.-key e) "Enter")
                                  (try
                                    (display-result (evaluate (.val input) eval-func))
                                    (catch err
                                        (debugger!)
                                        (display-result (str "ERROR: " (or err.stack err)))
                                      (console.log err))
                                    (finally (.val input "")))))))))

(defn display-result
  [str]
  (let [output ($ "#eval-result")]
    (.prop output "textContent" (String str))))

(defn evaluate
  [source eval-func]
  (let [output (compile source)]
    (if (:error output)
      (throw (:error output))
      (eval-func (:code output)))))

(defn close-connection
  []
  (.close emacs-connection)
  (set! emacs-connection nil))

(defn emacs-connect
  "Connect to emacs-org websocket"
  [url eval-func]
  (if emacs-connection (close-connection))
  )
