   (:require [goog.events :as events]
             [goog.events.EventType :as EventType]
             [cljs.core.async :as async :refer [>! <! put! chan]]
+            [cljs.reader :refer [read-string]]
             [om.core :as om :include-macros true]
             [om.dom :as dom :include-macros true]
             [goog.style :as gstyle]
             [cljs-workspace.morph :as morphic]
+            [om-sync.core :refer [om-sync]]
+            [om-sync.util :refer [tx-tag edn-xhr]]
             ; [clojure.browser.repl :as repl]
             )
   (:import [goog.events EventType]))

                         :BorderColor "black"
                         :BorderWidth 2}}))

(om/root
  morphic/morph
  app-state
  {:target (. js/document (getElementById "app"))})

;; snapshot the state when it is changed:

(def app-history (atom [@app-state]))

(defn pluralize [n w]
  (if (> n 1) 
      (str w "s")
      (str w)))

(add-watch app-state :history
  (fn [_ _ _ n]
    (when-not (= (last @app-history) n)
      (swap! app-history conj n))
    (let [c (count @app-history)]
        (prn (str c " Saved " (pluralize c "State"))))))

(om/root
  (fn [app owner]
    (om/component (dom/button #js {:onClick undo} "Undo!")))
  app-state 
  {:target (. js/document (getElementById "inspector"))})

  (defn undo [e]
    (when (> (count @app-history) 1)
      (swap! app-history pop)
      (reset! app-state (last @app-history))))

(defn morph [app owner]
  (reify
    om/IWillMount
    (will-mount [this]
      (let [mouse-move
              (async/map
                (fn [e] [(.-clientX e) (.-clientY e) (@app :id)])
                [(listen js/window EventType/MOUSEMOVE)])
            mouse-down
              (async/map
                (fn [e] (swap! clicked-morph (fn [_] (@app :id))))
                [(listen js/window EventType/MOUSEDOWN)])
            mouse-up
              (async/map
                (fn [e] (swap! clicked-morph (fn [_] (@app :id))))
                [(listen js/window EventType/MOUSEUP)])]
        (go (while true
              (om/update! app :mouse (<! mouse-move))))))
    om/IRender
    (render [this]
      (prn @clicked-morph)
      (dom/div (extract-props (:morph app)) (shape app)))))

(defn shape [app]
  (dom/div (extract-props (:shape app)) (render-submorphs app)))

(defn render-submorphs [app]
  (dom/div #js {:className "originNode"}
    (apply dom/div nil
      (om/build-all morph (:submorphs app)))))

(om/root
  morph
  app-state
  {:target (. js/document (getElementById "app"))})

(def app-state 
         (atom {:id 1
                :morph {:id 1 :Position {:x 0 :y 42}}
                :shape {:id 1
                        :BorderWidth 5
                        :BorderColor "rgb(0,0,0)"
                        :Fill "rgb(255,255,255)"
                        :Extent {:x 300 :y 300}}
