# this is required as we have "xml.py" file in the current package which replaces Python "xml" module on Python 2.7
from __future__ import absolute_import 

# Borrowed from
# https://bitbucket.org/formencode/official-formencode/src/3be5078c6030/formencode/doctest_xml_compare.py#cl-70

import xml.etree.ElementTree as ET
from parallels.core import messages


def reporter(msg):
    raise Exception(msg)


def compare_xml(x1, x2, reporter=reporter):
    if x1.tag != x2.tag:
        if reporter:
            reporter(messages.XML_TAGS_DO_NOT_MATCH % (x1.tag, x2.tag))
        return False
    for name, value in x1.attrib.items():
        if x2.attrib.get(name) != value:
            if reporter:
                reporter(
                    messages.XML_ATTRIBUTES_DO_NOT_MATCH % (
                        name, value, name, x2.attrib.get(name)
                    )
                )
            return False
    for name in x2.attrib:
        if name not in x1.attrib:
            if reporter:
                reporter(messages.XML_ATTRIBUTE_MISSING % name)
            return False
    if not text_compare(x1.text, x2.text):
        if reporter:
            reporter(messages.XML_TEXT_DIFFERS % (x1.text, x2.text))
        return False
    if not text_compare(x1.tail, x2.tail):
        if reporter:
            reporter(messages.XML_TAIL_DIFFERS % (x1.tail, x2.tail))
        return False
    cl1 = x1.getchildren()
    cl2 = x2.getchildren()
    if len(cl1) != len(cl2):
        if reporter:
            reporter(
                messages.XML_NUMBER_OF_CHILD_DIFFERS % (
                    x1.tag, len(cl1), len(cl2)
                )
            )
        return False
    i = 0
    for c1, c2 in zip(cl1, cl2):
        i += 1
        if not compare_xml(c1, c2, reporter=reporter):
            if reporter:
                reporter(messages.XML_CHILDREN_DO_NOT_MATCH % (i, c1.tag))
            return False
    return True


def text_compare(t1, t2):
    if not t1 and not t2:
        return True
    if t1 == '*' or t2 == '*':
        return True
    return (t1 or '').strip() == (t2 or '').strip()


def make_xml(s):
    return ET.XML('<xml>%s</xml>' % s)


def make_string(xml):
    if isinstance(xml, (str, unicode)):
        xml = make_xml(xml)
    s = ET.tostring(xml)
    if s == '<xml />':
        return ''
    assert s.startswith('<xml>') and s.endswith('</xml>'), repr(s)
    return s[5:-6]
