"""some pylint test utilities
"""
import sys
from glob import glob
from os.path import join, abspath, dirname, basename, exists, splitext
from cStringIO import StringIO

from pylint.interfaces import IReporter
from pylint.reporters import BaseReporter

PREFIX = abspath(dirname(__file__))

def fix_path():
    sys.path.insert(0, PREFIX)

SYS_VERS_STR = '%d%d' % sys.version_info[:2]

def get_tests_info(prefix, suffix):
    """get python input examples and output messages
    
    We use following conventions for input files and messages:
    for different inputs:
        don't test for python  <   x.y    ->  input   =  <name>_pyxy.py
        don't test for python  >=  x.y    ->  input   =  <name>_py_xy.py
    for one input and different messages:
        message for python     <=  x.y    ->  message =  <name>_pyxy.txt
        higher versions                   ->  message with highest num
    """
    result = []
    for fname in glob(join(PREFIX, 'input', prefix + '*' + suffix)):
        infile = basename(fname)
        fbase = splitext(infile)[0]
        # filter input files :
        pyrestr = fbase.rsplit('_py', 1)[-1] # like _26 or 26
        if pyrestr.isdigit(): # '24', '25'...
            if SYS_VERS_STR < pyrestr:
                continue
        if pyrestr.startswith('_') and  pyrestr[1:].isdigit():
            # skip test for higher python versions
            if SYS_VERS_STR >= pyrestr[1:]:
                continue
        messages = glob(join(PREFIX, 'messages', fbase + '*.txt'))
        # the last one will be without ext, i.e. for all or upper versions:
        if messages:
            for outfile in sorted(messages, reverse=True):
                py_rest = outfile.rsplit('_py', 1)[-1][:-4]
                if py_rest.isdigit() and SYS_VERS_STR >= py_rest:
                    break
        else:
            outfile = None
        result.append((infile, outfile))
    return result


TITLE_UNDERLINES = ['', '=', '-', '.']

class TestReporter(BaseReporter):
    """ store plain text messages 
    """
    
    __implements____ = IReporter
    
    def __init__(self):
        self.message_ids = {}
        self.reset()
        
    def reset(self):
        self.out = StringIO()
        self.messages = []
        
    def add_message(self, msg_id, location, msg):
        """manage message of different type and in the context of path """
        fpath, module, object, line, _ = location
        self.message_ids[msg_id] = 1
        if object:
            object = ':%s' % object
        sigle = msg_id[0]
        self.messages.append('%s:%3s%s: %s' % (sigle, line, object, msg))

    def finalize(self):
        self.messages.sort()
        for msg in self.messages:
            print >>self.out, msg
        result = self.out.getvalue()
        self.reset()
        return result
    
    def display_results(self, layout):
        """ignore layouts"""


# # # # #  pyreverse unittest utilities  # # # # # #

from logilab.common.testlib import TestCase
import os
import sys
from os.path import join

from logilab.astng import MANAGER



def _astng_wrapper(func, modname):
    return func(modname)


def _sorted_file(path):
    lines = [line.strip() for line in open(path).readlines()
             if (line.find('squeleton generated by ') == -1 and
                 not line.startswith('__revision__ = "$Id:'))]
    lines = [line for line in lines if line]
    lines.sort()
    return '\n'.join(lines)

def get_project(module, name=None):
    """return a astng project representation
    """
    manager = MANAGER
    # flush cache
    manager._modules_by_name = {}
    return manager.project_from_files([module], _astng_wrapper,
                                      project_name=name)

DEFAULTS = {'all_ancestors': None, 'show_associated': None,
            'module_names': None,
            'output_format': 'dot', 'diadefs_file': None, 'quiet': 0,
            'show_ancestors': None, 'classes': (), 'all_associated': None,
            'mode': 'PUB_ONLY', 'show_builtin': False, 'only_classnames': False}

class Config(object):
    """config object for tests"""
    def __init__(self):
        for attr, value in DEFAULTS.items():
            setattr(self, attr, value)

class FileTC(TestCase):
    """base test case for testing file output"""

    generated_files = ()

    def setUp(self):
        self.expected_files = [join(dirname(abspath(__file__)), 'data', file)
                               for file in self.generated_files]

    def tearDown(self):
        for fname in self.generated_files:
            try:
                os.remove(fname)
            except:
                continue

    def _test_same_file(self, index):
        generated_file = self.generated_files[index]
        expected_file = self.expected_files[index]
        generated = _sorted_file(generated_file)
        expected = _sorted_file(expected_file)

        from difflib import unified_diff
        files = "\n *** expected : %s, generated : %s \n"  % (
            expected_file, generated_file)
        self.assertEqual(expected, generated, '%s%s' % (
            files, '\n'.join(line for line in unified_diff(
            expected.splitlines(), generated.splitlines() ))) )
        os.remove(generated_file)


def build_file_case(filetc):
    for i in range(len(filetc.generated_files)):
        setattr(filetc, 'test_same_file_%s' %i,
                lambda self, index=i: self._test_same_file(index))
