# -*- coding:utf-8; tab-width:4; mode:python -*-

import string
import os
import socket
import traceback
import logging

import configobj
import validate

from commodity.log import CapitalLoggingFormatter
from commodity.pattern import Bunch

from . import gvars
from .const import PREGO_TMP_BASE, PREGO_TMP, term, PREGO_SPECS

basedir = os.getcwd()


class Interpolator(object):
    fixed_vars = Bunch(dict(
        basedir      = os.path.relpath(basedir),
        fullbasedir  = os.path.abspath(basedir),
        pid          = os.getpid(),
        tmpbase      = PREGO_TMP_BASE,
        tmp          = PREGO_TMP,
        hostname     = socket.gethostname(),
        ))

    def __init__(self):
        set_testpath()
        testdir, testname  = os.path.split(gvars.testpath)

        self.vars = self.fixed_vars.copy()
        self.vars.update(
            dict(
                testdir      = os.path.relpath(testdir),
                fulltestdir  = os.path.abspath(testdir),
                testfilename = testname,
                ))
        self.vars.update(gvars.context)

    def apply(self, text):
        if not isinstance(text, basestring):
            return text

        return string.Template(text).safe_substitute(self.vars)


def create_file(fpath, *args):
    path, name = os.path.split(fpath)
    if path in [PREGO_TMP, PREGO_TMP_BASE]:
        try:
            os.makedirs(path)
        except OSError:
            pass

    return file(fpath, *args)


class PregoStreamHandler(logging.StreamHandler):
    pass


def set_logger_default_formatter(logger=None):
    logger = logger or logging.getLogger()
    formatstr = '[%(levelcapital)s] %(message)s'
    set_logger_formatter(logger, CapitalLoggingFormatter(formatstr))


def set_logger_formatter(logger, formatter):
    for handler in logger.handlers:
        handler.setFormatter(formatter)


def create_logger(name):
    retval = logging.getLogger(name)
#    retval.setLevel(logging.DEBUG)
    retval.propagate = True
    return retval


class StatusFilter(logging.Filter):
    def __init__(self, item=None):
        self.item = item
        super(StatusFilter, self).__init__()

    def filter(self, record):
        if self.item is None:
            return True

        msg = string.Template(record.msg)
        values = {}
        try:
            values['name'] = self.item.name
            values['status'] = self.item.status.pretty()
        except AttributeError:
            pass

        record.msg = "{0}{1}".format(msg.safe_substitute(values), term().normal)
        return True


def update_obj(dst, src):
    for key, value in src.items():
        setattr(dst, key, value)


def load_default_config(dest):
    config = configobj.ConfigObj(configspec=PREGO_SPECS)
    config.validate(validate.Validator())
    update_obj(dest, config['ui'])


def set_testpath():
    if gvars.testpath is None:
        return

    it = iter(traceback.extract_stack())
    for frame in it:
        if frame[3] == 'testMethod()':
            gvars.testpath = it.next()[0]
