# coding: utf-8
import re
import os
import traceback
from urlparse import urlparse

import vim
from floo import dmp_monkey
dmp_monkey.monkey_patch()

from floo import sublime
from floo import AgentConnection
from floo import msg
from floo import shared as G
from floo import utils
from floo.vim_protocol import Protocol


utils.load_settings()

# enable debug with let floo_log_level = 'debug'
floo_log_level = vim.eval('floo_log_level')
if floo_log_level:
    msg.LOG_LEVEL = msg.LOG_LEVELS.get(floo_log_level.upper(), msg.LOG_LEVELS['MSG'])

agent = None


def global_tick():
    """a hack to make vim evented like"""
    if agent:
        agent.tick()
    sublime.call_timeouts()


def CursorHold(*args, **kwargs):
    global_tick()
    vim.command('call feedkeys("f\\e", "n")')


def CursorHoldI(*args, **kwargs):
    global_tick()
    linelen = int(vim.eval("col('$')-1"))
    if linelen > 0:
        if int(vim.eval("col('.')")) == 1:
            vim.command("call feedkeys(\"\<Right>\<Left>\",'n')")
        else:
            vim.command("call feedkeys(\"\<Left>\<Right>\",'n')")
    else:
        vim.command("call feedkeys(\"\ei\",'n')")


# TODO: code smell
def maybeSelectionChanged(*args, **kwargs):
    if agent and agent.protocol:
        agent.protocol.maybe_selection_changed(vim.current.buffer)


def maybeBufferChanged():
    if agent and agent.protocol:
        agent.protocol.maybe_buffer_changed(vim.current.buffer)


def joinroom(room_url):
    global agent
    print("room url is %s" % room_url)
    secure = G.SECURE
    parsed_url = urlparse(room_url)
    port = parsed_url.port
    if parsed_url.scheme == 'http':
        if not port:
            port = 3148
        secure = False
    result = re.match('^/r/([-\w]+)/([-\w]+)/?$', parsed_url.path)
    if not result:
        return sublime.error_message('Unable to parse your URL!')

    (owner, room) = result.groups()
    G.PROJECT_PATH = os.path.realpath(os.path.join(G.COLAB_DIR, owner, room))
    print("making dir %s" % G.PROJECT_PATH)
    utils.mkdir(G.PROJECT_PATH)

    print("joining room %s" % room_url)

    if agent:
        agent.stop()
    try:
        agent = AgentConnection(owner, room, host=parsed_url.hostname, port=port, secure=secure, on_auth=None, Protocol=Protocol)
        # owner and room name are slugfields so this should be safe
        agent.connect()
    except Exception as e:
        print(e)
        tb = traceback.format_exc()
        print(tb)


def partroom():
    if agent and G.CONNECTED:
        agent.stop()
    else:
        print('Unable to part room: You are not joined to a room.')

@@ -1146,50 +1146,51 @@
 )%0A%0A%0A
-# TODO: code smell%0Adef maybeSelectionChang
+def agent_and_protocol(func):%0A    def wrapp
 ed(*
@@ -1202,24 +1202,28 @@
  **kwargs):%0A
+    
     if agent
@@ -1239,32 +1239,147 @@
 t.protocol:%0A    
+        func(*args, **kwargs)%0A    return wrapped%0A%0A%0A@agent_and_protocol%0Adef maybeSelectionChanged(*args, **kwargs):%0A
     agent.protoc
@@ -1423,24 +1423,44 @@
 t.buffer)%0A%0A%0A
+@agent_and_protocol%0A
 def maybeBuf
@@ -1477,45 +1477,8 @@
 ():%0A
-    if agent and agent.protocol:%0A    
     
@@ -1531,24 +1531,115 @@
 t.buffer)%0A%0A%0A
+@agent_and_protocol%0Adef follow(follow_mode=None):%0A    agent.protocol.follow(follow_mode)%0A%0A%0A
 def joinroom

Make a decorator to check for agent and agent.protocol