import json
import os
import re
import subprocess

from .base import Base


class Source(Base):

    def __init__(self, vim):
        Base.__init__(self, vim)

        self.name = 'go'
        self.mark = '[go]'
        self.filetypes = ['go']
        self.input_pattern = r'[^. \t0-9]\.\w*'

    def get_complete_position(self, context):
        m = re.search(r'\w*$', context['input'])
        return m.start() if m else -1

    # Json output and convert vim syntax
    def gather_candidates(self, context):
        source = '\n'.join(self.vim.current.buffer).encode()
        buf_path = self.vim.current.buffer.name
        # TODO(zchee): Convert python code
        offset = self.vim.eval(
            "line2byte(line('.')) + (col('.')-2)"
        )

        process = subprocess.Popen([self.GoCodeBinary(),
                                    '-f=json',
                                    'autocomplete',
                                    buf_path,
                                    str(offset)],
                                   stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        process.stdin.write(source)
        stdout_data, stderr_data = process.communicate()
        result = json.loads(stdout_data.decode('utf-8'))

        try:
            return [self.ConvertCompletionData(x) for x in result[1]]
        except Exception:
            return []

    def ConvertCompletionData(self, complete):
        out = {
            'word': complete['name']
        }
        out['kind'] = complete['type']
        out['abbr'] = complete['class'] + ' ' + complete['name']
        out['info'] = complete['type']
        if complete['class'] == 'package':
            out['word'] += '.'
        elif complete['class'] == 'func':
            out['word'] += '('
            out['kind'].strip(complete['class'])
        elif complete['type'] == '[]string':
            out['word'] += '['

        return out

    def GoCodeBinary(self):
        try:
            binary_path = self.vim.vars['deoplete#sources#go#gocode_binary']
            if binary_path:
                if os.path.isfile(binary_path):
                    return binary_path
                else:
                    return None
        except Exception:
            return self.FindBinaryPath('gocode')

    def FindBinaryPath(self, cmd):
        def is_exec(fpath):
            return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

        fpath, fname = os.path.split(cmd)
        if fpath:
            if is_exec(cmd):
                return cmd
        else:
            for path in os.environ["PATH"].split(os.pathsep):
                path = path.strip('"')
                binary = os.path.join(path, cmd)
                if is_exec(binary):
                    return binary
        return None

@@ -1339,68 +1339,37 @@
     
-try:%0A            return %5Bself.ConvertCompletionData(x) for x
+out = %5B%5D%0A        for complete
  in 
@@ -1377,17 +1377,17 @@
 esult%5B1%5D
-%5D
+:
 %0A       
@@ -1391,148 +1391,186 @@
     
-except Exception:%0A            return %5B
+    word = complete%5B'name'%5D%0A            class_type = complete%5B'class'
 %5D%0A%0A    
-def ConvertCompletionData(self, complete):%0A        out = %7B%0A            'word': complete%5B'name'%5D
+        if class_type == 'package':%0A                word += '.'%0A            elif class_type == 'func':
 %0A   
@@ -1578,18 +1578,16 @@
     
-%7D%0A
         
 out%5B
@@ -1586,87 +1586,170 @@
     
-out%5B'kind'%5D = complete%5B'type'%5D%0A        out%5B'abbr'%5D = complete%5B'class'%5D + ' ' + 
+word += '('%0A            elif complete%5B'type'%5D == '%5B%5Dstring':%0A                word += '%5B'%0A%0A            out.append(dict(word=word,%0A                            abbr=
 comp
@@ -1752,32 +1752,33 @@
 complete%5B'name'%5D
+,
 %0A        out%5B'in
@@ -1774,121 +1774,83 @@
     
-out%5B'info'%5D = complete%5B'type'%5D%0A        if complete%5B'class'%5D == 'package':%0A            out%5B'word'%5D += '.'%0A
+                    kind='%7B:5%7D'.format(class_type) +%0A              
         
 elif
@@ -1837,36 +1837,37 @@
                 
-elif
+     
  complete%5B'class
@@ -1865,88 +1865,69 @@
 te%5B'
-class'%5D == 'func':%0A            out%5B'word'%5D += '('%0A            out%5B'kind'%5D.strip(
+type'%5D.replace('func', ''),%0A                            info=
 comp
@@ -1936,16 +1936,15 @@
 te%5B'
-class'%5D)
+type'%5D,
 %0A   
@@ -1952,77 +1952,169 @@
     
-elif complete%5B'type'%5D == '%5B%5Dstring':%0A            out%5B'word'%5D += '%5B'%0A%0A
+                    icase=1,%0A                            dup=1%0A                            ))%0A%0A        try:%0A            return out%0A        except Exception:%0A    
     
@@ -2124,19 +2124,18 @@
  return 
-out
+%5B%5D
 %0A%0A    de

Remove ConvertCompletionData() and fix create dict