 (defn send-heartbeat [socket]
   (websocket-send socket :heartbeat))
 
-(defn send-message [socket data]
-  (websocket-send socket :data (message data)))
-
-(defn send-event [socket name args]
-  (websocket-send socket :event :data (encode-json->string {:name name :args args})))
+(defn send-message
+  ([socket data] (websocket-send socket :message :data (message data)))
+  ([socket data callback] (websocket-send socket :message :data (message data) :callback callback)))
+
+(defn send-event
+  ([socket name args]
+     (websocket-send socket :event :data (encode-json->string {:name name :args args})))
+  ([socket name args callback]
+     (websocket-send socket :event :data (encode-json->string {:name name :args args})
+                     :callback callback)))
 
 (defn send-ack
   ([socket id] (websocket-send socket :ack :data (str id)))

(defn translate-message-type [type]
  (message-types (Integer/parseInt type)))

(defmulti websocket-message (fn [type & rest] (class type)))
(defmethod websocket-message Integer
  [type & {:keys [id endpoint data] :or {id "" endpoint ""}}]


(defn websocket-send [socket type & message-args]
  {:pre [(instance? WebsocketChannel socket)]}
  (let [seq-args ((:sequencer socket) type message-args)
        channel (:channel socket)
        endpoint (:endpoint socket)
        {:keys [id callback]} seq-args]
    (when (and callback id)
      (receive (->> channel
                    (map* translate-message)
                    (filter* #(= :ack (first %1))) ; [type _ _ _ _]
                    (map* #(translate-ack (last %1))) ; [_ _ _ _ data]
                    (filter* #(= id (first %1))) ; [id data]
                    (map* second)) 
               callback))
    (enqueue channel
             (apply websocket-message type
                    (into seq-args [:endpoint endpoint])))))

(defn websocket-sequencer []
  (let [counter (atom 0)]
    (fn [type message]
      (if (#{:message :json-message :event} type)
        (concat message [:id (swap! counter inc)])
        message))))

