         ;; :value only works for simple values
         :result :value)))
 
-(comment
-  (defn scroll-visible
-    "Make the given node visible by scrolling to it. Returns the bounding box in
-  screen coordinates (NOT page).
-  Tries to center the viewport around the element."
-    ([node] (scroll-visible @current-automation node))
-    ([{c :connection :as ctx} node]
-     (println "SCROLL-VISIBLE: " node ", resolved: " (dom/resolve-node c node))
-     (let [[ww wh] (evaluate ctx "[window.innerHeight, window.innerWidth]")
-           [center-x center-y] (:center (bounding-box ctx node))
-           scroll-x (int (- center-x (/ ww 2)))
-           scroll-y (int (- center-y (/ wh 2)))]
-       (println "SCROLL TO " scroll-x ", " scroll-y)
-       (evaluate ctx (format "window.scrollTo(%d,%d)" scroll-x scroll-y))
-       (let [{:keys [x y width height]} (bounding-box ctx node)
-             [sx sy] (evaluate ctx "[window.scrollX, window.scrollY]")
-             screen-x (- x sx)
-             screen-y (- y sy)]
-         (println "scroll at: " sx "," sy)
-         {:x screen-x
-          :y screen-y
-          :center [(Math/round (double (+ screen-x (/ width 2))))
-                   (Math/round (double (+ screen-y (/ height 2))))]})))))
-
-(defn- node-object-id [{c :connection} node]
+(defn- node-object-id [{c :connection :as ctx} node]
   (->> node (dom/resolve-node c) :object :object-id))
 
 (defn- eval-node [{c :connection :as ctx} node-or-object-id & fn-def-strings]

  "Wait for element to become visible, return true if element is visible, false otherwise."
  ([node] (visible @current-automation node))
  ([{c :connection :as ctx} node]
   (let [object-id (node-object-id ctx node)]
     (wait :render false
           (eval-node ctx object-id
                      "function() {"

            [clj-chrome-devtools.impl.connection :as connection]
            [clojure.core.async :as async :refer [go-loop go <!! <!]]
            [clojure.java.io :as io]
            [clojure.string :as str]
            [clojure.spec.alpha :as s]))

;; Define what a node reference is

(s/def ::node-id integer?)
(s/def ::node-ref (s/keys :req-un [::node-id]))

;; A hiccup selector is a vector of hiccup-like elements
;; [:div.some-class :a]
(s/def ::hiccup-selector (s/coll-of keyword?))

(s/def ::selector (s/or :css-selector string?
                        :hiccup-selector ::hiccup-selector))

(s/def ::node-like (s/or :node-ref ::node-ref
                         :selector ::selector))

(defn- selector->string [selector]
  (let [conformed-selector (s/conform ::selector selector)]
    (assert (not= conformed-selector ::s/invalid)
            (s/explain-str ::selector selector))
    (let [[selector-type selector-value] conformed-selector]
      (if (= selector-type :css-selector)
        selector-value
        (str/join " " (map name selector-value))))))

(declare sel1)

(defn- to-node-ref [ctx node-like]
  (let [conformed-node-like (s/conform ::node-like node-like)]
    (assert (not= conformed-node-like :s/invalid)
            (s/explain-str ::node-like node-like))
    (let [[ref-or-selector _] conformed-node-like]
      (if (= :node-ref ref-or-selector)
        node-like
        (sel1 ctx (selector->string node-like))))))

;; Automation context wraps a low-level CDP connection with state handling
(defrecord Automation [connection root])
