import unittest
import imp
import os
import errno
import sys
import glob
import re
import tempfile
import shutil
import inspect
import hashlib
from distutils.errors import *
import antlr3

def unlink(path):
    try:
        os.unlink(path)
    except OSError, exc:
        if exc.errno != errno.ENOENT:
            raise


class GrammarCompileError(Exception):
  """Grammar failed to compile."""
  pass


# At least on MacOSX tempdir (/tmp) is a symlink. It's sometimes dereferences,
# sometimes not, breaking the inspect.getmodule() function.
testbasedir = os.path.join(
    os.path.realpath(tempfile.gettempdir()),
    'antlr3-test')


class BrokenTest(unittest.TestCase.failureException):
    def __repr__(self):
        name, reason = self.args
        return '%s: %s: %s works now' % (
            (self.__class__.__name__, name, reason))


def broken(reason, *exceptions):
    '''Indicates a failing (or erroneous) test case fails that should succeed.
    If the test fails with an exception, list the exception type in args'''
    def wrapper(test_method):
        def replacement(*args, **kwargs):
            try:
                test_method(*args, **kwargs)
            except exceptions or unittest.TestCase.failureException:
                pass
            else:
                raise BrokenTest(test_method.__name__, reason)
        replacement.__doc__ = test_method.__doc__
        replacement.__name__ = 'XXX_' + test_method.__name__
        replacement.todo = reason
        return replacement
    return wrapper


dependencyCache = {}
compileErrorCache = {}

# setup java CLASSPATH
if 'CLASSPATH' not in os.environ:
    cp = []

    baseDir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
    libDir = os.path.join(baseDir, 'lib')

    jar = os.path.join(libDir, 'ST-4.0.1.jar')
    if not os.path.isfile(jar):
        raise DistutilsFileError(
            "Missing file '%s'. Grap it from a distribution package."
            % jar,
            )
    cp.append(jar)

    jar = os.path.join(libDir, 'antlr-2.7.7.jar')
    if not os.path.isfile(jar):
        raise DistutilsFileError(
            "Missing file '%s'. Grap it from a distribution package."
            % jar,
            )
    cp.append(jar)

    jar = os.path.join(libDir, 'junit-4.2.jar')
    if not os.path.isfile(jar):
        raise DistutilsFileError(
            "Missing file '%s'. Grap it from a distribution package."
            % jar,
            )
    cp.append(jar)

    cp.append(os.path.join(baseDir, 'runtime', 'Python', 'build'))

    classpath = '-cp "' + ':'.join([os.path.abspath(p) for p in cp]) + '"'

else:
    classpath = ''


class ANTLRTest(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        unittest.TestCase.__init__(self, *args, **kwargs)

        self.moduleName = os.path.splitext(os.path.basename(sys.modules[self.__module__].__file__))[0]
        self.className = self.__class__.__name__
        self._baseDir = None

        self.lexerModule = None
        self.parserModule = None

        self.grammarName = None
        self.grammarType = None


    def assertListEqual(self, a, b):
        if a == b:
            return

        import difflib
        a = [str(l) + '\n' for l in a]
        b = [str(l) + '\n' for l in b]

        raise AssertionError(''.join(difflib.unified_diff(a, b)))


    @property
    def baseDir(self):
        if self._baseDir is None:
            testName = 'unknownTest'
            for frame in inspect.stack():
                code = frame[0].f_code
                codeMod = inspect.getmodule(code)
                if codeMod is None:
                    continue

                # skip frames not in requested module
                if codeMod is not sys.modules[self.__module__]:
                    continue

                # skip some unwanted names
                if code.co_name in ('nextToken', '<module>'):
                    continue

                if code.co_name.startswith('test'):
                    testName = code.co_name
                    break

            self._baseDir = os.path.join(
                testbasedir,
                self.moduleName, self.className, testName)
            if not os.path.isdir(self._baseDir):
                os.makedirs(self._baseDir)

        return self._baseDir


    def _invokeantlr(self, dir, file, options, javaOptions=''):
        cmd = 'cd %s; java %s %s org.antlr.Tool -o . %s %s 2>&1' % (
            dir, javaOptions, classpath, options, file
            )
        fp = os.popen(cmd)
        output = ''
        failed = False
        for line in fp:
            output += line

            if line.startswith('error('):
                failed = True

        rc = fp.close()
        if rc is not None:
            failed = True

        if failed:
            raise GrammarCompileError(
                "Failed to compile grammar '%s':\n%s\n\n" % (file, cmd)
                + output
                )


    def compileGrammar(self, grammarName=None, options='', javaOptions=''):
        if grammarName is None:
            grammarName = self.moduleName + '.g'

        self._baseDir = os.path.join(
            testbasedir,
            self.moduleName)
        if not os.path.isdir(self._baseDir):
            os.makedirs(self._baseDir)

        if self.grammarName is None:
            self.grammarName = os.path.splitext(grammarName)[0]

        grammarPath = os.path.join(os.path.dirname(os.path.abspath(__file__)), grammarName)

        # get type and name from first grammar line
        grammar = open(grammarPath, 'r').read()
        m = re.match(r'\s*((lexer|parser|tree)\s+|)grammar\s+(\S+);', grammar, re.MULTILINE)
        assert m is not None, grammar
        self.grammarType = m.group(2)
        if self.grammarType is None:
            self.grammarType = 'combined'

        if self.grammarType is None:
            assert self.grammarType in ('lexer', 'parser', 'tree', 'combined'), self.grammarType

        # don't try to rebuild grammar, if it already failed
        if grammarName in compileErrorCache:
            return

        try:
        #     # get dependencies from antlr
        #     if grammarName in dependencyCache:
        #         dependencies = dependencyCache[grammarName]

        #     else:
        #         dependencies = []
        #         cmd = ('cd %s; java %s %s org.antlr.Tool -o . -depend %s 2>&1'
        #                % (self.baseDir, javaOptions, classpath, grammarPath))

        #         output = ""
        #         failed = False

        #         fp = os.popen(cmd)
        #         for line in fp:
        #             output += line

        #             if line.startswith('error('):
        #                 failed = True
        #             elif ':' in line:
        #                 a, b = line.strip().split(':', 1)
        #                 dependencies.append(
        #                     (os.path.join(self.baseDir, a.strip()),
        #                      [os.path.join(self.baseDir, b.strip())])
        #                     )

        #         rc = fp.close()
        #         if rc is not None:
        #             failed = True

        #         if failed:
        #             raise GrammarCompileError(
        #                 "antlr -depend failed with code %s on grammar '%s':\n\n"
        #                 % (rc, grammarName)
        #                 + cmd
        #                 + "\n"
        #                 + output
        #                 )

        #         # add dependencies to my .stg files
        #         templateDir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'tool', 'src', 'main', 'resources', 'org', 'antlr', 'codegen', 'templates', 'Python'))
        #         templates = glob.glob(os.path.join(templateDir, '*.stg'))

        #         for dst, src in dependencies:
        #             src.extend(templates)

        #         dependencyCache[grammarName] = dependencies

        #     rebuild = False
        #     for dest, sources in dependencies:
        #         if not os.path.isfile(dest):
        #             rebuild = True
        #             break

        #         for source in sources:
        #             if os.path.getmtime(source) > os.path.getmtime(dest):
        #                 rebuild = True
        #                 break


        #     if rebuild:
        #         self._invokeantlr(self.baseDir, grammarPath, options, javaOptions)

            self._invokeantlr(self.baseDir, grammarPath, options, javaOptions)

        except:
            # mark grammar as broken
            compileErrorCache[grammarName] = True
            raise


    def lexerClass(self, base):
        """Optionally build a subclass of generated lexer class"""

        return base


    def parserClass(self, base):
        """Optionally build a subclass of generated parser class"""

        return base


    def walkerClass(self, base):
        """Optionally build a subclass of generated walker class"""

        return base


    def __load_module(self, name):
        modFile, modPathname, modDescription \
                 = imp.find_module(name, [self.baseDir])

        return imp.load_module(
            name, modFile, modPathname, modDescription
            )


    def getLexer(self, *args, **kwargs):
        """Build lexer instance. Arguments are passed to lexer.__init__()."""

        if self.grammarType == 'lexer':
            self.lexerModule = self.__load_module(self.grammarName)
            cls = getattr(self.lexerModule, self.grammarName)
        else:
            self.lexerModule = self.__load_module(self.grammarName + 'Lexer')
            cls = getattr(self.lexerModule, self.grammarName + 'Lexer')

        cls = self.lexerClass(cls)

        lexer = cls(*args, **kwargs)

        return lexer


    def getParser(self, *args, **kwargs):
        """Build parser instance. Arguments are passed to parser.__init__()."""

        if self.grammarType == 'parser':
            self.lexerModule = self.__load_module(self.grammarName)
            cls = getattr(self.lexerModule, self.grammarName)
        else:
            self.parserModule = self.__load_module(self.grammarName + 'Parser')
            cls = getattr(self.parserModule, self.grammarName + 'Parser')
        cls = self.parserClass(cls)

        parser = cls(*args, **kwargs)

        return parser


    def getWalker(self, *args, **kwargs):
        """Build walker instance. Arguments are passed to walker.__init__()."""

        self.walkerModule = self.__load_module(self.grammarName + 'Walker')
        cls = getattr(self.walkerModule, self.grammarName + 'Walker')
        cls = self.walkerClass(cls)

        walker = cls(*args, **kwargs)

        return walker


    def writeInlineGrammar(self, grammar):
        # Create a unique ID for this test and use it as the grammar name,
        # to avoid class name reuse. This kinda sucks. Need to find a way so
        # tests can use the same grammar name without messing up the namespace.
        # Well, first I should figure out what the exact problem is...
        id = hashlib.md5(self.baseDir).hexdigest()[-8:]
        grammar = grammar.replace('$TP', 'TP' + id)
        grammar = grammar.replace('$T', 'T' + id)

        # get type and name from first grammar line
        m = re.match(r'\s*((lexer|parser|tree)\s+|)grammar\s+(\S+);', grammar, re.MULTILINE)
        assert m is not None, grammar
        grammarType = m.group(2)
        if grammarType is None:
            grammarType = 'combined'
        grammarName = m.group(3)

        assert grammarType in ('lexer', 'parser', 'tree', 'combined'), grammarType

        grammarPath = os.path.join(self.baseDir, grammarName + '.g')

        # dump temp grammar file
        fp = open(grammarPath, 'w')
        fp.write(grammar)
        fp.close()

        return grammarName, grammarPath, grammarType


    def writeFile(self, name, contents):
        testDir = os.path.dirname(os.path.abspath(__file__))
        path = os.path.join(self.baseDir, name)

        fp = open(path, 'w')
        fp.write(contents)
        fp.close()

        return path


    def compileInlineGrammar(self, grammar, options='', javaOptions='',
                             returnModule=False):
        # write grammar file
        grammarName, grammarPath, grammarType = self.writeInlineGrammar(grammar)

        # compile it
        self._invokeantlr(
            os.path.dirname(grammarPath),
            os.path.basename(grammarPath),
            options,
            javaOptions
            )

        if grammarType == 'combined':
            lexerMod = self.__load_module(grammarName + 'Lexer')
            parserMod = self.__load_module(grammarName + 'Parser')
            if returnModule:
                return lexerMod, parserMod

            lexerCls = getattr(lexerMod, grammarName + 'Lexer')
            lexerCls = self.lexerClass(lexerCls)
            parserCls = getattr(parserMod, grammarName + 'Parser')
            parserCls = self.parserClass(parserCls)

            return lexerCls, parserCls

        if grammarType == 'lexer':
            lexerMod = self.__load_module(grammarName)
            if returnModule:
                return lexerMod

            lexerCls = getattr(lexerMod, grammarName)
            lexerCls = self.lexerClass(lexerCls)

            return lexerCls

        if grammarType == 'parser':
            parserMod = self.__load_module(grammarName)
            if returnModule:
                return parserMod

            parserCls = getattr(parserMod, grammarName)
            parserCls = self.parserClass(parserCls)

            return parserCls

        if grammarType == 'tree':
            walkerMod = self.__load_module(grammarName)
            if returnModule:
                return walkerMod

            walkerCls = getattr(walkerMod, grammarName)
            walkerCls = self.walkerClass(walkerCls)

            return walkerCls
