from abc import ABCMeta, abstractmethod

from production.model import ProductionOrder, ProdStates
from typing import Union, List
from ._ProductionBox import ProductionBox


def _set_invalid_if_no_items(order):
    if not order.items:
        order.prod_state = ProdStates.INVALID


class OrderChangerProductionBox(ProductionBox):
    __metaclass__ = ABCMeta

    def order_modified(self, order):
        if not order.state:
            self.debug("{} - Order without state".format(self.name))

        initial_order_prod_state = order.prod_state
        if initial_order_prod_state == ProdStates.INVALID:
            self.debug("{:50} - Order ProdState [INVALID] - No modifications...", self.name)
        else:
            self.debug("{:50} - Order before modification:\n{}", self.name, str(order))
        altered_order = self.change_order(order)
        if isinstance(altered_order, list) and len(altered_order) > 0:
            for index, order_temp in enumerate(altered_order):
                try:
                    begin_message = "#region    - Order ID: {} - Order Index {}"
                    self.debug(begin_message, order_temp.order_id, index, extra={'simple': True})
                    self.debug("{:50} - Order Index {} after modification:\n{}", self.name, index, str(order_temp))
                    self.send_to_children(order_temp)
                finally:
                    final_message = "#endregion - Order ID: {} - Order Index {}"
                    self.debug(final_message, order_temp.order_id, index, extra={'simple': True})

        elif altered_order:
            _set_invalid_if_no_items(altered_order)
            if initial_order_prod_state != ProdStates.INVALID:
                self.debug("{:50} - Order after modification:\n{}", self.name, str(altered_order))
            self.send_to_children(altered_order)

        else:
            self.debug("{:50} - Order removed", self.name)

    @abstractmethod
    def change_order(self, order):
        # type: (ProductionOrder) -> Union[ProductionOrder, List[ProductionOrder]]

        raise NotImplementedError()
