#! /usr/bin/env python3

import os
import unittest

from flightgear.meta import sgprops
from flightgear.meta.sgprops import PropsHandlerMode


baseDir = os.path.dirname(__file__)

def testData(*args):
    return os.path.join(baseDir, "testData", *args)


class SGProps(unittest.TestCase):

    def test_parse(self):
        parsed = sgprops.readProps(testData("props1.xml")).node

        self.assertEqual(parsed.getValue("value"), 42)
        self.assertEqual(type(parsed.getValue("value")), int)

        valNode = parsed.getChild("value")
        self.assertEqual(valNode.parent, parsed)
        self.assertEqual(valNode.name, "value")

        self.assertEqual(valNode.value, 42)
        self.assertEqual(type(valNode.value), int)

        with self.assertRaises(sgprops.NoSuchChildError):
            missingNode = parsed.getChild("missing")

        things = parsed.getChildren("thing")
        self.assertEqual(len(things), 3)

        self.assertEqual(things[0], parsed.getChild("thing", 0));
        self.assertEqual(things[1], parsed.getChild("thing", 1));
        self.assertEqual(things[2], parsed.getChild("thing", 2));

        self.assertEqual(things[0].getValue("value"), "apple");
        self.assertEqual(things[1].getValue("value"), "lemon");
        self.assertEqual(things[2].getValue("value"), "pear");

    def test_create(self):
        pass

    def test_invalidIndex(self):
        filePath = testData("bad-index.xml")

        with self.assertRaises(sgprops.InvalidIndexStringError) as ctxManager:
            parsed = sgprops.readProps(filePath).node

        exc = ctxManager.exception # the exception that was raised
        self.assertEqual(exc.file, filePath)
        self.assertEqual(exc.line, 5)

    def test_include(self):
        parsed = sgprops.readProps(testData("props2.xml")).node

        # test that value in main file over-rides the one in the include
        self.assertEqual(parsed.getValue("value"), 33)

        # but these come from the included file
        self.assertEqual(parsed.getValue("value[1]"), 43)
        self.assertEqual(parsed.getValue("value[2]"), 44)

        subNode = parsed.getChild("sub")
        widgets = subNode.getChildren("widget")
        self.assertEqual(len(widgets), 4)

        self.assertEqual(widgets[0].value, 42)
        self.assertEqual(widgets[0].index, 0)

        self.assertEqual(widgets[1].value, 43)
        self.assertEqual(widgets[1].index, 1)

        self.assertEqual(widgets[2].value, 44)
        self.assertEqual(widgets[2].index, 2)

        self.assertEqual(widgets[3].value, 99)
        self.assertEqual(widgets[3].index, 100)

    def test_resilientMode(self):
        mainFile = testData("many-errors.xml")
        includedFile = testData("included-with-errors.xml")
        errors = sgprops.readProps(mainFile,
                                   mode=PropsHandlerMode.RESILIENT).errors

        expectedErrors = [
            # (exception name, XML file, line number in XML file)
            ('InvalidValueForIntegerPropertyError', mainFile, 9),
            ('InvalidValueForIntegerPropertyError', mainFile, 10),
            ('InvalidValueForIntegerPropertyError', mainFile, 11),
            ('InvalidValueForIntegerPropertyError', mainFile, 12),
            ('InvalidValueForIntegerPropertyError', mainFile, 13),
            ('InvalidValueForIntegerPropertyError', mainFile, 14),
            ('InvalidValueForIntegerPropertyError', includedFile, 3),
            ('InvalidValueForIntegerPropertyError', includedFile, 4),
            ('InvalidValueForFloatingPointPropertyError', includedFile, 8),
            ('InvalidValueForFloatingPointPropertyError', includedFile, 9),
            ('InvalidIndexStringError', mainFile, 21),
            ('InvalidIndexStringError', mainFile, 22),
            ('InvalidIndexStringError', mainFile, 23),
            ('IncludeFileNotFoundError', mainFile, 26),
            ('UnknownOrUnhandledPropertyTypeError', mainFile, 27),
            ('InvalidValueForBooleanPropertyError', mainFile, 28),
            ('InvalidValueForBooleanPropertyError', mainFile, 29),
            ('InvalidValueForBooleanPropertyError', mainFile, 30),
        ]

        self.assertEqual(len(errors), len(expectedErrors))

        for found, expected in zip(errors, expectedErrors):
            self.assertIsInstance(found, getattr(sgprops, expected[0]))
            self.assertEqual(found.file, expected[1])
            self.assertEqual(found.line, expected[2])


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