# -*- coding: utf-8 -*-

import logging
import json
import os.path
from completor import Completor, vim
from completor.compat import to_unicode
from completor.utils import ignore_exception

logger = logging.getLogger('completor')


class Go(Completor):
    filetype = 'go'
    trigger = r'(?:\w{2,}\w*|\.\w*)$'

    def get_offset(self):
        line, col = vim.current.window.cursor
        line2byte = vim.Function('line2byte')
        return line2byte(line) + col - 1

    def _complete_cmd(self):
        binary = self.get_option('gocode_binary') or 'gocode'
        cmd = [binary, '-f=csv',
               'autocomplete', self.filename, self.get_offset()]
        return cmd, '\n'.join(vim.current.buffer[:])

    def _doc_cmd(self):
        fname = self.filename
        binary = self.get_option('gogetdoc_binary') or 'gogetdoc'
        cmd = [binary, '-json', '-u']
        if not os.path.exists(fname):
            fname = self.tempname
            archive = ''
        else:
            cmd.append('-modified')
            content = '\n'.join(vim.current.buffer[:])
            archive = '\n'.join([fname, str(len(content)), content])
        cmd.extend(['-pos', '{}:#{}'.format(fname, self.get_offset())])
        return cmd, archive

    def get_cmd_info(self, action):
        if action == b'complete':
            cmd, input_content = self._complete_cmd()
        elif action in (b'doc', b'definition'):
            cmd, input_content = self._doc_cmd()
        else:
            cmd, input_content = [], ''
        return vim.Dictionary(
            cmd=cmd,
            ftype=self.filetype,
            is_daemon=False,
            is_sync=False,
            input_content=input_content,
        )

    def on_complete(self, items):
        res = []
        for item in items:
            parts = item.split(b',,')
            if len(parts) < 3:
                continue
            res.append({
                'word': parts[1],
                'menu': parts[2],
                'info': parts[2]
            })
        return res

    @ignore_exception()
    def on_doc(self, items):
        data = to_unicode(items[0], 'utf-8')
        spec = json.loads(data)
        _import = 'import "{}"'.format(spec['import'])
        doc = '\n\n'.join([_import, spec['decl'], spec['doc']])
        return [doc]

    @ignore_exception()
    def on_definition(self, items):
        data = to_unicode(items[0], 'utf-8')
        spec = json.loads(data)
        path, lnum, col = spec['pos'].rsplit(':', 2)
        return [{
            'filename': path,
            'lnum': lnum,
            'col': col,
            'name': spec['name']
        }]

@@ -305,16 +305,83 @@
 %5Cw*)$'%0A%0A
+    # Use guru for go to definition.%0A    use_guru_for_def = False%0A%0A
     def 
@@ -532,16 +532,165 @@
 ol - 1%0A%0A
+    def _gen_archive(self, fname):%0A        content = '%5Cn'.join(vim.current.buffer%5B:%5D)%0A        return '%5Cn'.join(%5Bfname, str(len(content)), content%5D)%0A%0A
     def 
@@ -1245,147 +1245,411 @@
     
-content = '%5Cn'.join(vim.current.buffer%5B:%5D)%0A            archive = '%5Cn'.join(%5Bfname, str(len(content)), content%5D)%0A        cmd.extend(%5B'-pos',
+archive = self._gen_archive(fname)%0A        cmd.extend(%5B'-pos', '%7B%7D:#%7B%7D'.format(fname, self.get_offset())%5D)%0A        return cmd, archive%0A%0A    def _def_cmd(self):%0A        guru = self.get_option('go_guru_binary')%0A        if not guru:%0A            return self._doc_cmd()%0A        fname = self.filename%0A        self.use_guru_for_def = True%0A        cmd = %5Bguru, '-json', '-modified', 'definition',%0A              
  '%7B%7D
@@ -1679,33 +1679,32 @@
 f.get_offset())%5D
-)
 %0A        return 
@@ -1700,39 +1700,56 @@
     return cmd, 
-archive
+self._gen_archive(fname)
 %0A%0A    def get_cm
@@ -1882,34 +1882,17 @@
 ion 
-in (
+== 
 b'doc'
-, b'definition')
 :%0A  
@@ -1930,32 +1930,119 @@
 self._doc_cmd()%0A
+        elif action == b'definition':%0A            cmd, input_content = self._def_cmd()%0A
         else:%0A  
@@ -2958,32 +2958,39 @@
  to_unicode(
+b''.join(
 items
-%5B0%5D
+)
 , 'utf-8')%0A 
@@ -3032,37 +3032,204 @@
     
-path, lnum, col = spec%5B'pos'%5D
+if self.use_guru_for_def:%0A            pos = spec%5B'objpos'%5D%0A            name = spec%5B'desc'%5D%0A        else:%0A            pos = spec%5B'pos'%5D%0A            name = spec%5B'name'%5D%0A        path, lnum, col = pos
 .rsp
@@ -3358,28 +3358,20 @@
 'name': 
-spec%5B'
 name
-'%5D
 %0A       

Add guru support for goto definition for golang