"""
Various test for checking that the dotparsing module is working properly.
The basic test is to compare PNG renderings of the original graph and the
parsed and saved version.
"""

import unittest

#import dot2tex.dotparsing as dotp
from dot2tex import dotparsing
import re, os, shutil, glob, sys, time

import ImageChops, Image

from os.path import join, basename, splitext, normpath
from dot2tex import dotparsing
import logging

# intitalize logging module
log = logging.getLogger("test_graphparser")
console = logging.StreamHandler()
console.setLevel(logging.WARNING)
# set a format which is simpler for console use
formatter = logging.Formatter('%(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
log.addHandler(console)


# Directory with test files
BASE_DIR = join(os.path.dirname(__file__), "testgraphs/")
TESTFILES_DIR = "parsetests"
TESTFILES_PATH = join(BASE_DIR, TESTFILES_DIR)

PNG_DIR = join(TESTFILES_PATH, 'pngs')
DOT_DIR = join(TESTFILES_PATH, 'dpdots')

graphparser = dotparsing.DotDataParser()


def equal(im1, im2):
    return ImageChops.difference(im1, im2).getbbox() is None


def compare_dot_file(dotfile):
    """Check that a dot file is correctly parsed

    """
    try:
        log.info('Processing %s', dotfile)
        basefilename = basename(dotfile)
        basefilenamenoext = os.path.splitext(basefilename)[0]
        f = open(dotfile)
        try:
            data = f.read()
        except:
            log.warning('Could not open %s', dotfile)
            raise
        f.close()
        try:
            graph = graphparser.parse_dot_data(data)
            # create a dotparsing version of the dot file
            newfilename = normpath(join(DOT_DIR, basefilename + '.new'))
            f = open(newfilename, 'w')
            f.write(str(graph))
            f.close()
        except:
            log.exception('Failed to parse and save %s', basefilename)
            raise
        origpngfilename = join(PNG_DIR, basefilenamenoext + '.png')
        newpngfilename = join(PNG_DIR, basefilenamenoext + '.new.png')
        # create PNG from original dot file
        syscmd = 'dot -Tpng %s > %s' % (dotfile, origpngfilename)
        log.debug("Run %s", syscmd)
        err = os.system(syscmd)
        if err:
            log.warning("Failed to create original %s", origpngfilename)
            #failedfiles.append(basefilename)
            raise
        # create PNG from dot file generated by dotparsing
        syscmd = 'dot -Tpng %s > %s' % (newfilename, newpngfilename)
        log.debug("Run %s", syscmd)
        err = os.system(syscmd)
        if err:
            log.warning("Failed to create new %s", origpngfilename)
            return -1
        # load and compare images
        try:
            imorig = Image.open(origpngfilename)
            imnew = Image.open(newpngfilename)
        except:
            log.exception('Could not load %s images', basefilename)
            raise
        if equal(imorig, imnew):
            log.info('%s matches.', basefilename)
            # remove files
            os.remove(origpngfilename)
            os.remove(newpngfilename)
            os.remove(newfilename)
            return 1

        else:
            log.warning('%s did not match!', basefilename)
            return 0
    except:
        log.exception('Failed to process %s', basefilename)
        raise


def test_dotfile(filename):
    return compare_dot_file(join(TESTFILES_PATH, filename))


class DotparsingTest(unittest.TestCase):
    def setUp(self):
        if not os.path.exists(PNG_DIR):
            os.mkdir(PNG_DIR)
        if not os.path.exists(DOT_DIR):
            os.mkdir(DOT_DIR)

    def test_ids(self):
        self.assertEqual(test_dotfile("ids.dot"), 1)

    def test_multilines(self):
        self.assertEqual(test_dotfile("multilines.dot"), 1)

    def test_subgraphs(self):
        self.assertEqual(test_dotfile("subgraphs.dot"), 1)

    def test_quoting(self):
        self.assertEqual(test_dotfile("quoting.dot"), 1)

    def test_unicode1(self):
        self.assertEqual(test_dotfile("unicode1.dot"), 1)

    def test_current(self):
        self.assertEqual(test_dotfile("current.dot"), 1)

    def test_ports(self):
        self.assertEqual(test_dotfile("ports.dot"), 1)


if __name__ == "__main__":
    unittest.main()

