"""
Test on graph compression.

"""
import unittest
import tempfile

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


class TestUnambiguousCompression(unittest.TestCase):
    """This class yields many subtests about 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 = {
            'diacli.lp'                      : RESULT_DIACLI,
            'double_biclique_unambiguous.lp' : RESULT_DDIAMUN,
            'bipartite.lp'                   : RESULT_BIP,
            'testblocks.lp'                  : RESULT_BLO,
            'partition.lp'                   : RESULT_PARTITION,
            'perfectfit.lp'                  : RESULT_PFC,
            'prio_deg.lp'                    : RESULT_PRIODEG,
            'clique.lp'                      : RESULT_CLIQUE,
            'star.lp'                        : RESULT_STAR,
            'concomp.lp'                     : RESULT_CC,
            'ecoli_2896-53.gml'              : RESULT_ECOLI,
            'order.lp'                       : RESULT_ORDER,
            'test.graphml'                   : RESULT_GRAPHML,
            'unclique.lp'                    : RESULT_UNCLIQUE,
            'one_edge.lp'                    : RESULT_ONEDGE,
            'test.gml'                       : RESULT_TESTGML,
            '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."""
        tmp = tempfile.NamedTemporaryFile('w', delete=False)
        tmp.close()
        with self.subTest(filename=input_filename):
            print('TEST CASE:', input_filename)
            cfg = config.Configuration(
                infile=input_filename,
                outfile=tmp.name,
                outformat='bbl',
                loglevel='CRITICAL',
            )
            recipes.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')
            )




# Expected results of tested cases
RESULT_DIACLI = """
NODE	n
NODE	r
NODE	p
NODE	q
NODE	e
NODE	b
NODE	m
NODE	a
NODE	o
NODE	c
NODE	j
NODE	d
NODE	g
NODE	l
NODE	s
NODE	f
IN	l	PWRN-a-3-1
IN	s	PWRN-a-3-1
IN	p	PWRN-a-3-1
IN	q	PWRN-a-4-2
IN	o	PWRN-a-4-2
IN	m	PWRN-a-4-1
IN	n	PWRN-a-4-1
IN	g	PWRN-a-1-1
IN	PWRN-a-3-1	PWRN-a-1-1
IN	r	PWRN-a-1-1
IN	j	PWRN-a-1-1
IN	f	PWRN-a-1-1
IN	PWRN-a-4-1	PWRN-a-3-2
IN	a	PWRN-a-2-1
IN	d	PWRN-a-2-1
IN	e	PWRN-a-2-2
IN	b	PWRN-a-2-2
IN	PWRN-a-4-2	PWRN-a-2-2
IN	c	PWRN-a-2-2
EDGE	PWRN-a-3-1	PWRN-a-3-2	1.0
EDGE	PWRN-a-1-1	PWRN-a-1-1	1.0
EDGE	PWRN-a-4-1	PWRN-a-4-2	1.0
EDGE	b	c	1.0
EDGE	PWRN-a-2-1	PWRN-a-2-2	1.0
EDGE	m	n	1.0
"""

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

RESULT_DDIAMUN = """
NODE\td2
NODE\th
NODE\tn
NODE\tq
NODE\te
NODE\tc
NODE\td
NODE\ti
NODE\tm2
NODE\tg
NODE\tp
NODE\tf1
NODE\tb2
NODE\ta
NODE\tf2
NODE\tj
NODE\tb1
NODE\tm
NODE\to
NODE\tl
IN\tf2\tPWRN-a-2-1
IN\tj\tPWRN-a-2-1
IN\tg\tPWRN-a-2-1
IN\tf1\tPWRN-a-2-1
IN\tPWRN-a-3-1\tPWRN-a-2-1
IN\tm\tPWRN-a-5-1
IN\tm2\tPWRN-a-5-1
IN\tPWRN-a-4-1\tPWRN-a-3-2
IN\td2\tPWRN-a-1-1
IN\td\tPWRN-a-1-1
IN\ta\tPWRN-a-1-1
IN\tq\tPWRN-a-1-2
IN\te\tPWRN-a-1-2
IN\tc\tPWRN-a-1-2
IN\tb2\tPWRN-a-1-2
IN\tb1\tPWRN-a-1-2
IN\to\tPWRN-a-1-2
IN\tp\tPWRN-a-3-1
IN\tl\tPWRN-a-3-1
IN\th\tPWRN-a-2-2
IN\ti\tPWRN-a-2-2
IN\tPWRN-a-5-1\tPWRN-a-4-1
IN\tn\tPWRN-a-4-1
EDGE\tPWRN-a-5-1\tn\t1.0
EDGE\tPWRN-a-2-1\tPWRN-a-2-2\t1.0
EDGE\tf1\tg\t1.0
EDGE\tPWRN-a-1-1\tPWRN-a-1-2\t1.0
EDGE\tPWRN-a-3-1\tPWRN-a-3-2\t1.0
EDGE\tPWRN-a-4-1\tq\t1.0
EDGE\tb1\tc\t1.0
"""


RESULT_BLO = """
NODE\tf
NODE\td
NODE\tm
NODE\ti
NODE\ta
NODE\th
NODE\te
NODE\tg
NODE\tc
NODE\tb
NODE\tj
IN\te\tPWRN-a-2-1
IN\tPWRN-a-3-1\tPWRN-a-2-1
IN\ta\tPWRN-a-3-1
IN\tc\tPWRN-a-3-1
IN\tb\tPWRN-a-3-1
IN\td\tPWRN-a-3-1
IN\tg\tPWRN-a-4-1
IN\tf\tPWRN-a-4-1
IN\th\tPWRN-a-4-1
IN\ti\tPWRN-a-1-1
IN\tj\tPWRN-a-1-1
IN\tPWRN-a-4-1\tPWRN-a-1-1
IN\tm\tPWRN-a-1-1
EDGE\tPWRN-a-2-1\tPWRN-a-2-1\t1.0
EDGE\tPWRN-a-3-1\tf\t1.0
EDGE\tPWRN-a-4-1\tl\t1.0
EDGE\tPWRN-a-1-1\tPWRN-a-1-1\t1.0
"""

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

RESULT_CLIQUE = """
NODE\tc
NODE\tb
NODE\ta
NODE\td
IN\tc\tPWRN-a-1-1
IN\tb\tPWRN-a-1-1
IN\ta\tPWRN-a-1-1
IN\td\tPWRN-a-1-1
EDGE\tPWRN-a-1-1\tPWRN-a-1-1\t1.0
"""

RESULT_STAR = """
NODE\tc
NODE\td
NODE\tb
NODE\te
IN\tc\tPWRN-a-1-2
IN\td\tPWRN-a-1-2
IN\tb\tPWRN-a-1-2
IN\te\tPWRN-a-1-2
EDGE\ta\tPWRN-a-1-2\t1.0
"""

RESULT_CC = """
EDGE\t23\t42\t1.0
NODE\t2
NODE\t5
NODE\t3
NODE\t4
NODE\t6
NODE\t1
IN\t1\tPWRN-1-1-1
IN\t6\tPWRN-1-1-1
IN\t4\tPWRN-1-1-2
IN\t2\tPWRN-1-1-2
IN\t5\tPWRN-1-1-2
IN\t3\tPWRN-1-1-2
EDGE\tPWRN-1-1-1\tPWRN-1-1-2\t1.0
NODE\tb
NODE\tc
NODE\td
NODE\te
IN\tb\tPWRN-a-1-2
IN\tc\tPWRN-a-1-2
IN\td\tPWRN-a-1-2
IN\te\tPWRN-a-1-2
EDGE\ta\tPWRN-a-1-2\t1.0
"""

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

RESULT_PFC = """
NODE\tj
NODE\tl
NODE\tb
NODE\tg
NODE\th
NODE\ta
NODE\td
NODE\tc
NODE\te
NODE\tf
NODE\ti
IN\tPWRN-a-2-1\tPWRN-a-1-2
IN\th\tPWRN-a-1-2
IN\ti\tPWRN-a-1-2
IN\tb\tPWRN-a-1-1
IN\tPWRN-a-3-1\tPWRN-a-1-1
IN\ta\tPWRN-a-1-1
IN\tj\tPWRN-a-3-2
IN\tl\tPWRN-a-3-2
IN\td\tPWRN-a-3-1
IN\tc\tPWRN-a-3-1
IN\te\tPWRN-a-2-1
IN\tg\tPWRN-a-2-1
IN\tf\tPWRN-a-2-1
IN\tPWRN-a-3-2\tPWRN-a-2-2
EDGE\tPWRN-a-3-1\tPWRN-a-3-2\t1.0
EDGE\tPWRN-a-2-1\tPWRN-a-2-2\t1.0
EDGE\tPWRN-a-1-1\tPWRN-a-1-2\t1.0
"""

RESULT_ECOLI = """
NODE\tR_VALabc
NODE\tR_DHAD1
NODE\tR_VALt2r
IN\tR_VALabc\tPWRN-R_DHAD1-1-1
IN\tR_DHAD1\tPWRN-R_DHAD1-1-1
IN\tR_VALt2r\tPWRN-R_DHAD1-1-1
EDGE\tPWRN-R_DHAD1-1-1\tPWRN-R_DHAD1-1-1\t1.0
NODE\tRXN-14213
NODE\tRXN-14200
NODE\tR_DTMPK
IN\tRXN-14213\tPWRN-RXN-14200-1-1
IN\tRXN-14200\tPWRN-RXN-14200-1-1
IN\tR_DTMPK\tPWRN-RXN-14200-1-1
EDGE\tPWRN-RXN-14200-1-1\tPWRN-RXN-14200-1-1\t1.0
NODE\tR_EX_26dap_M_LPAREN_e_RPAREN_
NODE\tRXN-14246
NODE\tR_DAPE
IN\tR_EX_26dap_M_LPAREN_e_RPAREN_\tPWRN-RXN-14246-1-1
IN\tRXN-14246\tPWRN-RXN-14246-1-1
IN\tR_DAPE\tPWRN-RXN-14246-1-1
EDGE\tPWRN-RXN-14246-1-1\tPWRN-RXN-14246-1-1\t1.0
EDGE\tNADH-KINASE-RXN\tR_NADK\t1.0
NODE\tR_G1PACT
NODE\tGLUCOSAMINEPNACETYLTRANS-RXN
NODE\tR_PGAMT
NODE\tPHOSACETYLGLUCOSAMINEMUT-RXN
NODE\tR_AMANAPE
NODE\tR_EX_acgam_LPAREN_e_RPAREN_
IN\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-2-1\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-1-1
IN\tPHOSACETYLGLUCOSAMINEMUT-RXN\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-1-1
IN\tGLUCOSAMINEPNACETYLTRANS-RXN\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-2-1
IN\tR_AMANAPE\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-2-1
IN\tR_EX_acgam_LPAREN_e_RPAREN_\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-2-1
IN\tR_G1PACT\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-1-2
IN\tR_PGAMT\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-1-2
EDGE\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-1-1\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-1-2\t1.0
EDGE\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-2-1\tPWRN-GLUCOSAMINEPNACETYLTRANS-RXN-2-1\t1.0
NODE\tR_GLGC
NODE\tRXN-10770
NODE\tGLYMALTOPHOSPHORYL-RXN
IN\tR_GLGC\tPWRN-GLYMALTOPHOSPHORYL-RXN-1-1
IN\tRXN-10770\tPWRN-GLYMALTOPHOSPHORYL-RXN-1-1
IN\tGLYMALTOPHOSPHORYL-RXN\tPWRN-GLYMALTOPHOSPHORYL-RXN-1-1
EDGE\tPWRN-GLYMALTOPHOSPHORYL-RXN-1-1\tPWRN-GLYMALTOPHOSPHORYL-RXN-1-1\t1.0
"""

RESULT_TESTGML = """
NODE\tg
NODE\tb
NODE\tm
NODE\ts
NODE\td
NODE\tv
NODE\tw
NODE\tf
NODE\tc
IN\td\tPWRN-b-1-1
IN\tw\tPWRN-b-1-1
IN\tc\tPWRN-b-1-1
IN\ts\tPWRN-b-1-1
IN\tb\tPWRN-b-1-1
IN\tf\tPWRN-b-2-2
IN\tPWRN-b-3-2\tPWRN-b-2-2
IN\tg\tPWRN-b-2-2
IN\tm\tPWRN-b-3-2
IN\tv\tPWRN-b-3-2
EDGE\tl\tPWRN-b-3-2\t1.0
EDGE\tl\tp\t1.0
EDGE\tPWRN-b-1-1\tPWRN-b-1-1\t1.0
EDGE\tm\tv\t1.0
EDGE\tc\tf\t1.0
EDGE\tb\tPWRN-b-2-2\t1.0
"""

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

RESULT_ORDER = """
NODE\t4
NODE\ta
NODE\t6
NODE\t5
IN\t4\tPWRN-4-1-1
IN\ta\tPWRN-4-1-1
IN\t6\tPWRN-4-1-1
IN\t5\tPWRN-4-1-1
EDGE\ta\ta\t1.0
EDGE\tPWRN-4-1-1\t10\t1.0
"""

RESULT_GRAPHML = """
NODE\t2
NODE\t3
NODE\t1
NODE\t4
IN\t1\tPWRN-1-1-1
IN\t4\tPWRN-1-1-1
IN\t3\tPWRN-1-1-2
IN\t2\tPWRN-1-1-2
EDGE\tPWRN-1-1-1\tPWRN-1-1-2\t1.0
"""

RESULT_ONEDGE = """
EDGE\ta\tb\t1.0
"""

RESULT_TESTGML = """
NODE\tc
NODE\tw
NODE\tf
NODE\tv
NODE\ts
NODE\tb
NODE\td
NODE\tg
NODE\tm
IN\tc\tPWRN-b-1-1
IN\tb\tPWRN-b-1-1
IN\tw\tPWRN-b-1-1
IN\td\tPWRN-b-1-1
IN\ts\tPWRN-b-1-1
IN\tg\tPWRN-b-2-2
IN\tf\tPWRN-b-2-2
IN\tPWRN-b-3-2\tPWRN-b-2-2
IN\tv\tPWRN-b-3-2
IN\tm\tPWRN-b-3-2
EDGE\tb\tPWRN-b-2-2\t1.0
EDGE\tc\tf\t1.0
EDGE\tPWRN-b-1-1\tPWRN-b-1-1\t1.0
EDGE\tm\tv\t1.0
EDGE\tl\tp\t1.0
EDGE\tl\tPWRN-b-3-2\t1.0
"""
