         (save-excursion
           (hlt-unhighlight-region 0 (buffer-size)))))
     floobits-user-highlights))
+
+(defun floobits-process-live-p (process)
+  "Returns non-nil if PROCESS is alive.
+  A process is considered alive if its status is `run', `open',
+  `listen', `connect' or `stop'."
+  (memq (process-status process)
+    '(run open listen connect stop)))
+
+(defmacro floo-get-item (alist key)
+  "just grab an element from an alist"
+  (list 'cdr (list 'assoc-string key alist)))
+
+(defmacro floo-set-item (alist key value)
+  "set an element in an alist"
+  (list 'add-to-list alist (list 'cons key value)))
+
+(defun floobits-load-floorc ()
+  "loads floorc file vars"
+  (condition-case nil
+    (progn
+      (with-temp-buffer
+        (insert-file-contents "~/.floorc")
+        (goto-char 1)
+        (let ((strings (split-string (buffer-string) "\n" t)))
+          (loop for s in strings do
+            (let ((substrings (split-string s " " t)))
+              (set (intern (concat "floobits-" (car substrings))) (cadr substrings)))))))
+  (error nil))
+  (if (or (not (boundp 'floobits-username)) (string= "" floobits-username))
+    (error "Floobits username not found. Please define a username and secret in ~/.floorc"))
+  (if (or (not (boundp 'floobits-secret)) (string= "" floobits-secret))
+    (error "Floobits secret not found. Please define a username and secret in ~/.floorc")))
+
+(defun floobits-listener (process response)
+  (setq floobits-agent-buffer (concat floobits-agent-buffer response))
+  (let ((position (search "\n" floobits-agent-buffer)))
+    (when position
+      (floobits-switch (substring floobits-agent-buffer 0 position))
+      (setq floobits-agent-buffer
+      (substring floobits-agent-buffer
+        (if (> (length floobits-agent-buffer) position) (+ 1 position) position)))
+      (floobits-listener process ""))))
+
+(defun floobits-create-connection ()
+  (floobits-launch-agent)
+  (setq floobits-conn (open-network-stream "floobits" nil floobits-agent-host floobits-agent-port))
+  (set-process-coding-system floobits-conn 'utf-8 'utf-8)
+  (process-kill-without-query floobits-conn)
+  (set-process-filter floobits-conn 'floobits-listener))
+
+(defun floobits-destroy-connection ()
+  (when floobits-conn
+    (message "Destroying Floobits conn")
+    (floobits-remove-hooks)
+    (delete-process floobits-conn)
+    (delete-process floobits-python-agent)
+    (floobits-initialize)
+    (setq floobits-python-agent nil)
+    (message "")))
+
+(defun floobits-filter-func (condp lst)
+  (delq nil
+  (mapcar (lambda (x) (and (funcall condp x) x)) lst)))
+
+(defun floobits-agent-listener (proc string)
+  ; todo: check for 'started'
+  ; (when (buffer-live-p (process-buffer proc))
+  (with-current-buffer "*Floobits*"
+    (let ((moving (= (point) (process-mark proc))))
+      ;; Insert the text, advancing the process marker.
+      (goto-char (process-mark proc))
+      (insert (concat "floobits agent says: " string))
+      (set-marker (process-mark proc) (point))
+      (if moving (goto-char (process-mark proc))))))
+
+(defun floobits-launch-agent ()
+  (condition-case nil
+    (progn
+      (delete-process floobits-python-agent))
+    (error nil))
+  (message "Launching Floobits python agent...")
+  (setq floobits-python-agent (start-process "" "*Floobits*" "python" floobits-python-path))
+  (switch-to-buffer "*Floobits*")
+  (set-process-filter floobits-python-agent 'floobits-agent-listener)
+  (accept-process-output floobits-python-agent 2)
+  (process-kill-without-query floobits-python-agent))
+
+(defun floobits-send-to-agent (req event)
+  (if (floobits-process-live-p floobits-conn)
+    (progn
+      (floo-set-item 'req 'name event)
+      (process-send-string floobits-conn (concat (json-encode req) "\n")))
+    (progn
+      (message "Connection to floobits died :(")
+      (floobits-destroy-connection))))
+
+(defun floobits-get-text (begin end)
+  (buffer-substring-no-properties begin end))
+
+(defun floobits-post-command-func ()
+  "used for grabbing changes in point for highlighting"
+  (floobits-buffer-list-change)
+  (floobits-send-highlight))
+
+(defun floobits-event-user_input (req)
+  (floo-set-item 'req 'response (read-from-minibuffer (floo-get-item req 'prompt) (floo-get-item req 'initial)))
+  (floobits-send-to-agent req 'user_input))
+
+(defun floobits-event-rename_buf (req)
+  (let* ((old-path (floo-get-item req 'old_path))
+         (new-path (floo-get-item req 'path))
+         (buf (get-file-buffer old-path)))
+    (message "renaming %s to %s" old-path new-path)
+    (rename-file old-path new-path 1)
+    (when buf
+      (with-current-buffer buf
+        (rename-buffer new-path)
+        (set-visited-file-name new-path)
+        (set-buffer-modified-p nil)))))
+
+(defun floobits-send-highlight (&optional ping)
+  (when (eq (_floobits-is-buffer-public (current-buffer)) t)
+    (let* ((name (buffer-file-name (current-buffer)))
+           (mark (or (mark) -1))
+           (current (list
+             (cons 'point (or (point) -1))
+             (cons 'mark mark)
+             (cons 'name (or name "")))))
+      (unless (or ping (equal current floobits-current-position))
+        (setq floobits-current-position current)
+        (let ((req (list
+            (cons 'ranges (vector (vector mark mark)))
+            (cons 'full_path name)
+            (cons 'ping ping))))
+          (floobits-send-to-agent req 'highlight))))))
+
+(defun _floobits-is-buffer-public (buf)
+  (let ((name (buffer-name buf)))
+    (cond
+      ((string="*" (substring name 0 1)) nil)
+      ((string=" " (substring name 0 1)) nil)
+      ((_floobits-is-buffer-shared buf) t)
+      (t nil))))
+
+(defun _floobits-is-path-shared (path)
+  (let ((length (length floobits-share-dir)))
+    (cond
+     ((eq 0 length) nil)
+     ((< (length path) length) nil)
+     ((string= floobits-share-dir (substring path 0 length)) t)
+     (t nil))))
+
+(defun _floobits-is-buffer-shared (buf)
+  (_floobits-is-path-shared (buffer-file-name buf)))
+
+(defun floobits-get-public-buffers ()
+  "returns buffers that aren't internal to emacs"
+  (floobits-filter-func '_floobits-is-buffer-public (buffer-list)))
+
+(defun floobits-get-buffer-text (buffer)
+  "returns properties free text of buffer with name (name)"
+  (with-current-buffer buffer)
+  ; (with-current-buffer (set-buffer (get-buffer-create name))
+    (buffer-substring-no-properties (point-min) (point-max)))
+
+(defun floobits-event-disconnect (req)
+  (message "Disconnected: %s" (floo-get-item req 'reason)))
+
+(defun floobits-event-room_info (req)
+  (setq floobits-workspace (floo-get-item req 'workspace_name))
+  (message "Successfully joined workspace %s" floobits-workspace)
+  (setq floobits-share-dir (floo-get-item req 'project_path))
+  (message "project path is %s" floobits-share-dir)
+  (setq floobits-perms (append (floo-get-item req 'perms) nil))
+  (floobits-add-hooks)
+  (dired floobits-share-dir))
+
+(defun floobits-event-join (req)
+  (message "%s" req)
+  (message "%s joined the workspace"  (floo-get-item req 'username)))
+
+(defun floobits-event-part (req)
+  (message "%s" req)
+  (message "%s left the workspace" (floo-get-item req 'username)))
+
+(defun floobits-event-create_view (req)
+  (message "opening file %s" (floo-get-item req 'full_path))
+  (find-file (floo-get-item req 'full_path))
+  (floobits-buffer-list-change))
+
+(defun floobits-event-focus (req)
+  (find-file (floo-get-item req 'full_path))
+  (goto-char (+ 1 (floo-get-item req 'offset))))
 
 (defun floobits-apply-highlight (user_id buffer ranges)
   (let* ((key (list user_id (buffer-file-name buffer)))

  (interactive)
  (floobits-send-to-agent () 'open_workspace))

(defun _floobits-is-buffer-public (buf)
  (let ((name (buffer-name buf)))
    (cond
      ((string="*" (substring name 0 1)) nil)
      ((string=" " (substring name 0 1)) nil)
      ((_floobits-is-buffer-shared buf) t)
      (t nil))))

(defun _floobits-is-path-shared (path)
  (let ((length (length floobits-share-dir)))
    (cond
     ((eq 0 length) nil)
     ((< (length path) length) nil)
     ((string= floobits-share-dir (substring path 0 length)) t)
     (t nil))))

(defun _floobits-is-buffer-shared (buf)
  (_floobits-is-path-shared (buffer-file-name buf)))

(defun floobits-get-public-buffers ()
  "returns buffers that aren't internal to emacs"
  (floobits-filter-func '_floobits-is-buffer-public (buffer-list)))

(defun floobits-get-buffer-text (buffer)
  "returns properties free text of buffer with name (name)"
  (with-current-buffer buffer)
  ; (with-current-buffer (set-buffer (get-buffer-create name))
    (buffer-substring-no-properties (point-min) (point-max)))

(defun floobits-event-disconnect (req)
  (message "Disconnected: %s" (floo-get-item req 'reason)))

(defun floobits-event-room_info (req)
  (setq floobits-workspace (floo-get-item req 'workspace_name))
  (message "Successfully joined workspace %s" floobits-workspace)
  (setq floobits-share-dir (floo-get-item req 'project_path))
  (message "project path is %s" floobits-share-dir)
  (setq floobits-perms (append (floo-get-item req 'perms) nil))
  (floobits-add-hooks)
  (dired floobits-share-dir))

(defun floobits-event-join (req)
  (message "%s" req)
  (message "%s joined the workspace"  (floo-get-item req 'username)))

(defun floobits-event-part (req)
  (message "%s" req)
  (message "%s left the workspace" (floo-get-item req 'username)))

(defun floobits-event-create_view (req)
  (message "opening file %s" (floo-get-item req 'full_path))
  (find-file (floo-get-item req 'full_path))
  (floobits-buffer-list-change))

(defun floobits-event-focus (req)
  (find-file (floo-get-item req 'full_path))
  (goto-char (+ 1 (floo-get-item req 'offset))))

;;;###autoload
(defun floobits-clear-highlights ()
  "Clears all highlights"

            (cons 'old_path old-name))))
        (floobits-send-to-agent req 'rename_buf))
      (message "You don't have permission to rename buffers in this workspace."))))

;;;###autoload
(defun floobits-summon ()
