"""
Test on oriented graph compression.

"""
import unittest
import tempfile

from powergrasp import commons
from powergrasp import recipes
from powergrasp import solving
from powergrasp import config


class TestOrientedUnambiguousCompression(unittest.TestCase):
    """This class yields many subtests about oriented and unambiguous
    compression results.

    The test case and associated results are defined in setUp() method.
    Bubble outputs are comparated, excluding comments and empty lines.

    The unambiguous compression is important : bubble comparison is sensitive
    to powernodes numbers and related.
    However, it resists to multiple connected components.

    """

    def setUp(self):
        self.test_cases = {
            # 'oriented_clique.lp'      : RESULT_CLIQUE,
            'oriented_double_edge.lp' : RESULT_DOUBLE_EDGE,
            'oriented_lattice.lp'     : RESULT_LATTICE,
            'oriented_overlap.lp'     : RESULT_OVERLAP,
            'oriented_simple.lp'      : RESULT_SIMPLE,
            'empty.lp'                : '',
        }


    def unified_bubble(self, bubble_lines):
        """Return the set of comparable lines found in given bubble lines"""
        # filter out comments and blank lines
        return set(line.strip() for line in bubble_lines
                   if not line.startswith('#') and len(line.strip()) > 0)

    def unified_bubble_from_file(self, bubble_file):
        """Return the set of comparable lines found in given bubble file"""
        with open(bubble_file) as fd:
            return self.unified_bubble(fd)

    def assert_equality(self, input_filename, expected_bubble):
        """call assertEqual to compare given bubble and bubble generated by
        compressing given graph."""
        # create the temp file to be write by the compression
        tmp = tempfile.NamedTemporaryFile('w', delete=False)
        tmp.close()
        # launch the compression itself, then compare result with expected
        with self.subTest(filename=input_filename):
            print('TEST CASE:', input_filename)
            cfg = config.Configuration.fields_for_oriented_graph(
                infile=input_filename,
                outfile=tmp.name,
                outformat='bbl',
                loglevel='CRITICAL',
            )
            recipes.oriented_powergraph(cfg=cfg)
            expected = self.unified_bubble(expected_bubble)
            found = self.unified_bubble_from_file(tmp.name)
            self.assertEqual(expected, found)


    def test_cases(self):
        for filename, expected in self.test_cases.items():
            self.assert_equality(
                commons.test_case(filename),
                expected.split('\n')
            )


RESULT_OVERLAP = """
NODE\tc
NODE\tb
NODE\td
NODE\ta
NODE\te
NODE\tf
IN\te\tPWRN-a-3-2
IN\tf\tPWRN-a-3-2
IN\tPWRN-a-3-2\tPWRN-a-2-2
IN\tb\tPWRN-a-1-2
IN\ta\tPWRN-a-1-2
IN\tc\tPWRN-a-1-1
IN\tPWRN-a-2-2\tPWRN-a-1-1
IN\td\tPWRN-a-1-1
EDGE\tb\tPWRN-a-3-2\t1.0
EDGE\tPWRN-a-1-1\tPWRN-a-1-2\t1.0
EDGE\tg\tPWRN-a-2-2\t1.0
"""

RESULT_CLIQUE = """
"""

RESULT_LATTICE = """
NODE\tf
NODE\ti
NODE\te
NODE\tc
NODE\tg
IN\tf\tPWRN-a-2-1
IN\tc\tPWRN-a-2-1
IN\tg\tPWRN-a-2-1
IN\ti\tPWRN-a-1-1
IN\te\tPWRN-a-1-1
IN\tPWRN-a-2-1\tPWRN-a-1-2
EDGE\tPWRN-a-2-1\th\t1.0
EDGE\tc\td\t1.0
EDGE\tPWRN-a-1-1\tPWRN-a-1-2\t1.0
EDGE\tb\td\t1.0
EDGE\ta\tc\t1.0
EDGE\ta\tb\t1.0
"""
RESULT_DOUBLE_EDGE = """
NODE\te
NODE\tc
NODE\ta
NODE\td
NODE\tb
IN\ta\tPWRN-a-1-1
IN\tb\tPWRN-a-1-1
IN\tc\tPWRN-a-1-2
IN\te\tPWRN-a-1-2
IN\td\tPWRN-a-1-2
EDGE\tPWRN-a-1-1\tPWRN-a-1-2\t1.0
EDGE\te\ta\t1.0
"""
RESULT_SIMPLE = """
NODE\tb
NODE\td
NODE\ta
NODE\tc
IN\ta\tPWRN-a-1-1
IN\tb\tPWRN-a-1-1
IN\td\tPWRN-a-1-2
IN\tc\tPWRN-a-1-2
EDGE\tPWRN-a-1-1\tPWRN-a-1-2\t1.0
EDGE\ta\te\t1.0
EDGE\te\tb\t1.0
"""
