class TestJumpHandling(TestCase):
    """
    This class groups together tests related to checking and handling jump
    labels in the circuit schematic.
    """

    def test_jump_sanity(self):
        """
        jump_sanity checks for whether an element in the complete system matrix
        is a jump, a component or no connection.
        param - 3 dimensional array (3 level nested list) of elements.
        param -  the sheet, row, column position.
        param -  an indicator dictionary about whether the element is a jump, a component or null.
        result - a modification to the indicator dictionary object.
        """
        from simulations.network_reader import jump_sanity, scrub_elements

        print()
        print('*'*80)
        print('Testing whether a jump can be identitifed on a circuit schematic element')
        test_matrix = [
            [
                ['wire', '', 'dyxcsdc', 'jump1', 'Resistor'],
                [' ', '', ' jump2', ' \n ', ' wire '],
            ],
            [
                ['wire', '', 'dyxcsdc', 'jump1', 'Resistor'],
                [' ', '', ' jump2', ' \n ', ' wire '],
            ],
        ]

        def repeat_test(sheet, row, column, expected_val):
            """
            A quick test method that takes the co-ordinates and
            checks the expected value.
            """
            test_element = {"exist":0, "jump":1}
            jump_sanity(test_matrix, test_element, sheet, row, column)
            self.assertEqual(test_element, expected_val)
            return

        repeat_test(0, 0, 0, {"exist":0})
        repeat_test(0, 0, 1, {})
        repeat_test(0, 0, 2, {"exist":0})
        repeat_test(0, 0, 3, {"jump":1})
        repeat_test(0, 0, 4, {"exist":0})
        # empty space cannot be handled and is treated as an element
        repeat_test(0, 1, 0, {"exist":0})
        repeat_test(0, 1, 1, {})
        # trailing empty space turns jump into an element
        repeat_test(0, 1, 2, {"exist":0})
        # newline character is seen as an element
        repeat_test(0, 1, 3, {"exist":0})
        repeat_test(0, 1, 4, {"exist":0})

        # Repitition to check for multiple sheets.
        repeat_test(1, 0, 0, {"exist":0})
        repeat_test(1, 0, 1, {})
        repeat_test(1, 0, 2, {"exist":0})
        repeat_test(1, 0, 3, {"jump":1})
        repeat_test(1, 0, 4, {"exist":0})
        repeat_test(1, 1, 0, {"exist":0})
        repeat_test(1, 1, 1, {})
        repeat_test(1, 1, 2, {"exist":0})
        repeat_test(1, 1, 3, {"exist":0})
        repeat_test(1, 1, 4, {"exist":0})

        print()

        return


    def test_jump_checking(self):
        """
        jump_checking - checks if a jump label is legal
        jumps have to be extreme elements in a branch
        jumps cannot be next to each other
        params - complete circuit matrix, and sheet, row, col co-ordinates
        params - rows, columns in that particular sheet
        params - list of circuit spreadsheet names
        returns/modifies - jump list adding a legal jump to it
        """
        from simulations.network_reader import jump_checking
        import simulations.circuit_exceptions as CktEx

        print()
        print('*'*80)
        print('Testing the jump_checking function')
        print()

        test_matrix = [
            [
                ['', '', 'wire', '', ''],
                ['', '', 'wire', '', ''],
                ['dyxcsdc', 'wire', 'wire', 'Resistor', 'jump1'],
                ['', '', 'wire', '', ''],
                ['', '', 'wire', '', ''],
                ['', '', 'wire', '', ''],
            ],
        ]
        test_jump = []
        test_nw_name = ['test1',]
        test_no_of_rows = len(test_matrix[0])
        test_no_of_cols = len(test_matrix[0][0])

        # jump1 is a legal jump
        jump_checking(test_matrix, test_jump, 0, 2, 4, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertEqual(test_jump[-1], [0, 2, 4, 'jump1', 'left'])

        # jump2 is at a node. Exception is not specially stating that it cannot be a node.
        test_matrix[0][2][2] = 'jump2'
        result = jump_checking(test_matrix, test_jump, 0, 2, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)
        test_matrix[0][2][2] = 'wire'

        # A legal jump at the extreme bottom
        test_matrix[0][5][2] = 'jump2'
        jump_checking(test_matrix, test_jump, 0, 5, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertEqual(test_jump[-1], [0, 5, 2, 'jump2', 'up'])

        # Illegal - jump not extreme element on branch.
        test_matrix[0][4][2] = 'jump3'
        result = jump_checking(test_matrix, test_jump, 0, 4, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)
        test_matrix[0][4][2] = 'wire'

        # jump2 is not extreme in a branch. Exception is not specially stating that it cannot be next to a node.
        test_matrix[0][1][2] = 'jump3'
        result = jump_checking(test_matrix, test_jump, 0, 1, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)

        test_matrix[0][0][2] = ''
        # This should raise an exception because a jump should not be next to a node.
        # But this test fails
        # result = jump_checking(test_matrix, test_jump, 0, 1, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        # self.assertTrue(len(result) > 0)

        # Illegal - two jumps next to each other
        test_matrix[0][0][2] = 'jump3'
        result = jump_checking(test_matrix, test_jump, 0, 0, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)

        # Resetting the element below makes it a legal jump
        test_matrix[0][1][2] = 'xyz'
        jump_checking(test_matrix, test_jump, 0, 0, 2, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertEqual(test_jump[-1], [0, 0, 2, 'jump3', 'down'])

        # Illegal - not extreme element in a branch
        test_matrix[0][2][1] = 'jump4'
        result = jump_checking(test_matrix, test_jump, 0, 2, 1, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)

        # Illegal - jumps next to each other
        test_matrix[0][2][0] = 'jump5'
        result = jump_checking(test_matrix, test_jump, 0, 2, 0, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)
        # Restting the jump to the right to an element makes it a legal jump
        test_matrix[0][2][1] = 'xyz'
        jump_checking(test_matrix, test_jump, 0, 2, 0, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertEqual(test_jump[-1], [0, 2, 0, 'jump5', 'right'])

        # Illegal - jump labels next to each other
        test_matrix[0][0][1] = 'jump6'
        result = jump_checking(test_matrix, test_jump, 0, 0, 1, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertTrue(len(result) > 0)

        # Legal jump when element to the right is reset to a component.
        test_matrix[0][0][2] = 'compo'
        jump_checking(test_matrix, test_jump, 0, 0, 1, test_no_of_rows, test_no_of_cols, test_nw_name)
        self.assertEqual(test_jump[-1], [0, 0, 1, 'jump6', 'right'])

        return


    def test_jump_node_check(self):
        """
        jump_node_check - checks whether a jump label is next to a node.
        param - entire circuit matrix
        param - list of nodes
        param - a direction in which a particular node has an element
        param - index of that particular node
        param - list of circuit spreadsheet names
        result - throws an error if in the direction specified for the node,
        there is a jump label in the adjacent cell. Adjacent cell is measured
        with respect to the node.
        """

        from simulations.network_reader import jump_node_check

        print()
        print('*'*80)
        print('Testing the jump_node_check function')
        print()

        test_matrix = [
            [
                ['', '', 'wire', '', ''],
                ['', '', 'wire', '', ''],
                ['dyxcsdc', 'wire', 'wire', 'Resistor', 'jump1'],
                ['', '', 'wire', '', ''],
                ['', '', 'wire', '', ''],
                ['', '', 'wire', '', ''],
            ],
        ]
        test_node_list = [
            [0, 2, 2]
        ]
        test_nw_name = ['test1',]

        result = jump_node_check(test_matrix, test_node_list, 'left', 0, test_nw_name)
        self.assertTrue(len(result) == 0)

        test_matrix[0][2][1] = 'jump2'
        result = jump_node_check(test_matrix, test_node_list, 'left', 0, test_nw_name)
        self.assertTrue(len(result) > 0)

        test_matrix[0][2][1] = 'xyz'
        test_matrix[0][2][0] = 'jump2'
        result = jump_node_check(test_matrix, test_node_list, 'left', 0, test_nw_name)
        self.assertTrue(len(result) == 0)

        test_matrix[0][1][2] = 'jump3'
        result = jump_node_check(test_matrix, test_node_list, 'up', 0, test_nw_name)
        self.assertTrue(len(result) > 0)

        test_matrix[0][1][2] = 'xyz'
        test_matrix[0][0][2] = 'jump3'
        result = jump_node_check(test_matrix, test_node_list, 'up', 0, test_nw_name)
        self.assertTrue(len(result) == 0)

        test_matrix[0][3][2] = 'jump4'
        result = jump_node_check(test_matrix, test_node_list, 'down', 0, test_nw_name)
        self.assertTrue(len(result) > 0)

        test_matrix[0][3][2] = 'xyz'
        test_matrix[0][4][2] = 'jump4'
        result = jump_node_check(test_matrix, test_node_list, 'down', 0, test_nw_name)
        self.assertTrue(len(result) == 0)

        print()

        return