import pytest
from calculate.variables.loader import CalculateIniParser, Define


@pytest.mark.vars
class TestCalculateIni:
    def test_section_values(self):
        ini_parser = CalculateIniParser()

        input_text = ("[section]\n"
                      "varval1 = value1\n")

        parsed_lines = [{'start_section': (['section'], 1)},
                        {'define_key': ('varval1', 'value1',
                                        Define.assign, 2)},
                        ]

        parse_result = list(ini_parser.parse(input_text))
        for parsed_line, result_line in zip(parsed_lines, parse_result):
            assert parsed_line == result_line

    def test_simple_calculate_ini_with_comments(self):
        ini_parser = CalculateIniParser()

        input_text = ("[section]\n"
                      "varval1 = value1\n"
                      "# some comment\n"
                      "varval2 += value2\n"
                      "varval3 -= value3\n")

        parsed_lines = [{'start_section': (['section'], 1)},
                        {'define_key': ('varval1', 'value1',
                                        Define.assign, 2)},
                        {'define_key': ('varval2', 'value2',
                                        Define.append, 4)},
                        {'define_key': ('varval3', 'value3',
                                        Define.remove, 5)},
                        ]

        parse_result = list(ini_parser.parse(input_text))
        for parsed_line, result_line in zip(parsed_lines, parse_result):
            assert parsed_line == result_line

    def test_some_complex_section_calculate_ini(self):
        ini_parser = CalculateIniParser()

        input_text = ("[section][sub]\n"
                      "varval1 = value1\n"
                      "varval2 = value2\n"
                      "[section][sub2]\n"
                      "varval1 = value1\n"
                      "\n"
                      "[section2]\n"
                      "varval1 = value1\n")

        parsed_lines = [{'start_section': (['section', 'sub'], 1)},
                        {'define_key': ('varval1', 'value1',
                                        Define.assign, 2)},
                        {'define_key': ('varval2', 'value2',
                                        Define.assign, 3)},
                        {'start_section': (['section', 'sub2'], 4)},
                        {'define_key': ('varval1', 'value1',
                                        Define.assign, 5)},
                        {'start_section': (['section2'], 7)},
                        {'define_key': ('varval1', 'value1',
                                        Define.assign, 8)}]

        parse_result = list(ini_parser.parse(input_text))
        for parsed_line, result_line in zip(parsed_lines, parse_result):
            assert parsed_line == result_line

    def test_error(self):
        ini_parser = CalculateIniParser()

        input_text = '''[section
varval1 = value1
varval2 = value2
[section][sub2]
varval1 = value1
eee

[section2
varval4 = value4
[section][]
[section][][sub]
[section][][sub][]'''

        lines = [{'start_section': (['section', 'sub2'], 4)},
                 {'define_key': ('varval1', 'value1', Define.assign, 5)},
                 {'define_key': ('varval4', 'value4', Define.assign, 9)},
                 {'clear_section': (['section'], 10)}
                 ]
        parsed_lines = []

        errors = [(1, '[section'),
                  (2, 'varval1 = value1'),
                  (3, 'varval2 = value2'),
                  (6, 'eee'),
                  (8, '[section2'),
                  (11, '[section][][sub]'),
                  (12, '[section][][sub][]'),
                  ]
        parsed_errors = []

        for parsed_line in ini_parser.parse(input_text):
            if next(iter(parsed_line)) == 'error':
                parsed_errors.append(parsed_line['error'])
            else:
                parsed_lines.append(parsed_line)

        assert len(parsed_errors) == len(errors)

        for error, parsed_error in zip(errors, parsed_errors):
            assert parsed_error == error
        for line, parsed_line in zip(lines, parsed_lines):
            assert parsed_line == line

    def test_clear_section(self):
        ini_parser = CalculateIniParser()

        parse_result = next(ini_parser.parse("[section][test][]\n"))
        assert parse_result == {'clear_section': (['section', 'test'], 1)}
