import logging
import xml.sax

from cache_functions import UsersInfoCache
from xml.etree import cElementTree as eTree

from typing import List

from messageprocessorutil import UuidMessageProcessor
from mwrepository import ProductRepository
from production.manager import ProductionManager
from production.model import ProductionOrder, Item

from ._SystemOrderParser import SystemOrderParser

performance_event_logger = logging.getLogger("ProductionPerformanceEvent")


class OrderModifiedProcessor(UuidMessageProcessor):
    def __init__(self, production_manager, product_repository, user_cache_thread=None):
        # type: (ProductionManager, ProductRepository, UsersInfoCache) -> None
        super(OrderModifiedProcessor, self).__init__()
        self.production_manager = production_manager
        self.part_code_jit_lines = product_repository.get_all_part_code_jit_lines()
        self.user_cache_thread = user_cache_thread

    def parse_data(self, data):
        self._performance_log(data)
        handler = SystemOrderParser(self.part_code_jit_lines, user_cache_thread=self.user_cache_thread)
        xml.sax.parseString(data, handler)
        if handler.order.order_id == 0:
            return None

        self._order_items(handler.order.items)
        return handler.order

    @staticmethod
    def _performance_log(
        data,   # type: str
    ):
        # type (...) -> None

        try:
            data_xml = eTree.XML(data)
            order_id = (data_xml.find(".//Order") or {}).get("orderId", "")
            subject = data_xml.get("subject", "")
            event_type = data_xml.get("type", "")
            message = "Event - {:10} / {:20} / {}".format(order_id, subject, event_type)
            performance_event_logger.info(message)
        except Exception as _:
            performance_event_logger.exception("Error parsing event xml")

    def _order_items(self, items):
        # type: (List[Item]) -> None

        for item in items:
            item.items = sorted(item.items, key=lambda i: (i.sequence, i.part_code))
            for son in item.items:
                if len(son.items) > 0:
                    self._order_items(son.items)

    def call_business(self, order):
        # type: (ProductionOrder) -> None
        if order is not None:
            self.production_manager.order_modified(order)

    def format_response(self, message_bus, message, event, input_obj, result):
        # no response
        pass

    def format_exception(self, message_bus, message, event, input_obj, exception):
        # no response
        pass

    def format_parse_exception(self, message_bus, message, event, data, exception):
        # no response
        pass
