"""
AutoTag.py
"""

import os
import os.path
import fileinput
import sys
import vim
import logging
from collections import defaultdict

# global vim config variables used (all are g:autotag<name>):
# name purpose
# maxTagsFileSize a cap on what size tag file to strip etc
# ExcludeSuffixes suffixes to not ctags on
# VerbosityLevel logging verbosity (as in Python logging module)
# CtagsCmd name of ctags command
# TagsFile name of tags file to look for
# Disabled Disable autotag (enable by setting to any non-blank value)
# StopAt stop looking for a tags file (and make one) at this directory (defaults to $HOME)
GLOBALS_DEFAULTS = dict(maxTagsFileSize=1024 * 1024 * 7,
                        ExcludeSuffixes="py.tml.xml.text.txt",
                        VerbosityLevel=logging.DEBUG,
                        #VerbosityLevel=logging.WARNING,
                        CtagsCmd="ctags",
                        TagsFile="tags",
                        Disabled=0,
                        StopAt=0)

# Just in case the ViM build you're using doesn't have subprocess
if sys.version < '2.4':
    def do_cmd(cmd, cwd):
        """ Python 2.3 has no subprocess """
        old_cwd = os.getcwd()
        os.chdir(cwd)
        ch_out = os.popen2(cmd)[1]
        for _ in ch_out:
            pass
        os.chdir(old_cwd)

    import traceback

    def format_exc():
        """ replace missing format_exc() """
        return ''.join(traceback.format_exception(*list(sys.exc_info())))

else:
    import subprocess

    def do_cmd(cmd, cwd):
        """ Abstract subprocess """
        subprocess.call(cmd, shell=True, cwd=cwd)
        #p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd)
        #so = p.communicate()[0]
        #return so.split("\n")

    from traceback import format_exc


def vim_global(name, kind=str):
    """ Get global variable from vim, cast it appropriately """
    ret = GLOBALS_DEFAULTS.get(name, None)
    try:
        v = "autotag" + name
        v_buffer = "b:" + v
        exists_buffer = (vim.eval("exists('%s')" % v_buffer) == "1")
        v_global = "g:" + v
        exists_global = (vim.eval("exists('%s')" % v_global) == "1")
        if exists_buffer:
            ret = vim.eval(v_buffer)
        elif exists_global:
            ret = vim.eval(v_global)
        else:
            if isinstance(ret, int):
                vim.command("let %s=%s" % (v_global, ret))
            else:
                vim.command("let %s=\"%s\"" % (v_global, ret))
    finally:
        if kind == bool:
            ret = (ret not in [0, "0"])
        elif kind == int:
            ret = int(ret)
        elif kind == str:
            ret = str(ret)
    return ret


class VimAppendHandler(logging.Handler):
    """ Logger handler that finds a buffer and appends the log message as a new line """
    def __init__(self, name):
        logging.Handler.__init__(self)
        self.__name = name
        self.__formatter = logging.Formatter()

    def __findBuffer(self):
        """ Look for the named buffer """
        for b in vim.buffers:
            if b and b.name and b.name.endswith(self.__name):
                return b

    def emit(self, record):
        """ Emit the logging message """
        b = self.__findBuffer()
        if b:
            b.append(self.__formatter.format(record))


def setLoggerVerbosity():
    """ Set the verbosity of the logger """
    try:
        level = int(vim_global("VerbosityLevel"))
    except ValueError:
        level = GLOBALS_DEFAULTS["VerbosityLevel"]
    LOGGER.setLevel(level)


def makeAndAddHandler(logger, name):
    """ Make the handler and add it to the standard logger """
    ret = VimAppendHandler(name)
    logger.addHandler(ret)
    return ret