# -*- coding: utf-8 -*-

import re
from typing import Dict
from xml.etree import cElementTree as eTree

MUST_BE_LIST = ['TenderHistory', 'SaleLine', 'StateHistory', 'ServiceOrders', 'ServiceTenders', 'PaymentOrders']


def _parse_dict(
    dictionary,    # type: Dict
):
    # type: (...) -> Dict

    for key in dictionary.keys():
        is_int = re.match(r'^\s*\d+\s*$', dictionary[key])
        is_float = dictionary[key].count('.') == 1 and re.match(r'^\s*(\d*\.\d+)|(\d+\.\d*)\s*$', dictionary[key])
        if is_int:
            dictionary[key] = int(dictionary[key])
        elif is_float:
            dictionary[key] = float(dictionary[key])
    return dictionary


def _transform_xml_to_dict(
    xml_object,    # type: eTree
):
    # type: (...) -> Dict

    all_tags = [ch.tag for ch in xml_object.getchildren()]
    item = _parse_dict(dictionary=xml_object.attrib) if len(xml_object.items()) > 0 else {}

    if len(xml_object.getchildren()) > 0:
        for child in xml_object.getchildren():
            if all_tags.count(child.tag) > 0 and not item.get(child.tag):
                item[child.tag] = []

            if type(item.get(child.tag)) == list:
                child_data = _transform_xml_to_dict(xml_object=child)

                if type(child_data) == list:
                    item[child.tag].extend(child_data)
                else:
                    item[child.tag].append(child_data)
            else:
                item[child.tag] = _transform_xml_to_dict(xml_object=child)
    if xml_object.tag == "Properties":
        return item
    item = item if len(item.keys()) > 1 or len(item.values()) == 0 else item.get(item.keys()[0])
    if 'key' in item:
        item[item.pop('key')] = item.pop('value')
    return item


def _fix_redundancies(
    dict_object,   # type: Dict
):
    # type: (...) -> Dict

    for attribute in dict_object.keys():
        attr = dict_object.get(attribute)
        if attribute in MUST_BE_LIST or not isinstance(attr, list):
            continue
        if _is_empty_dict_list(attr):
            dict_object[attribute] = [] if attribute in MUST_BE_LIST else {}
            continue
        if _has_same_keys(attr):
            new_dict = {}
            for item in attr:
                new_dict.update(item)
            dict_object[attribute] = new_dict
    return dict_object

def _is_empty_dict_list(
    value,  # type: str
):
    # type: (...) -> bool

    return len(value) > 0 and value[0] == {}

def _has_same_keys(
    value,  # type: str
):
    # type: (...) -> bool

    keys = [prop.keys()[0] for prop in value]
    return keys.count(keys[0]) != len(keys) or len(keys) == 1

def convert_xml_to_dict(
    xml_object,    # type: eTree
):
    # type: (...) -> Dict

    dict_object = _transform_xml_to_dict(xml_object=xml_object)
    dict_object = _fix_redundancies(dict_object=dict_object)
    if 'Orders' in dict_object.keys():
        if type(dict_object.get('Orders')) != list:
            dict_object['Orders'] = [dict_object.get('Orders')]
        for i, order in enumerate(dict_object.get('Orders')):
            dict_object['Orders'][i] = _fix_redundancies(dict_object=dict_object['Orders'][i])
    return dict_object
