from logging import Logger
from mw_helper import convert_to_dict, ensure_list
from production.box import ProductionBox
from production.box._OrderChangerProductionBox import OrderChangerProductionBox
from production.manager import OrderChanger
from production.model import ProductionOrder
from typing import Optional, List, Union


class OrderPropertiesFilterBox(OrderChangerProductionBox):
    def __init__(
            self,
            name,                       # type: str
            sons,                       # type: Union[List[ProductionBox], ProductionBox]
            order_changer,              # type: OrderChanger
            order_property,             # type: str
            allowed_values=None,        # type: Optional[List[str]]
            excluded_values=None,       # type: Optional[List[str]]
            remove_order=True,          # type: bool
            tags_to_add=None,           # type: Optional[List[str]]
            logger=None                 # type: Optional[Logger]
    ):
        # type: (...) -> None

        super(OrderPropertiesFilterBox, self).__init__(name, sons, logger)
        self.order_changer = order_changer
        self.order_property = order_property
        self.allowed_values = convert_to_dict(ensure_list(allowed_values))
        self.excluded_values = convert_to_dict(ensure_list(excluded_values))
        self.remove_order = remove_order
        self.tags_to_add = ensure_list(tags_to_add)

    def change_order(
            self,
            order   # type: ProductionOrder
    ):
        # type: (...) -> Optional[ProductionOrder]

        if not self.order_property:
            return order

        order_property = str(getattr(order, self.order_property))
        is_excluded = len(self.excluded_values) > 0 and order_property in self.excluded_values
        is_not_allowed = len(self.allowed_values) > 0 and order_property not in self.allowed_values
        if is_excluded or is_not_allowed:
            self._tag_items(order)

            if self.remove_order:
                return None
            else:
                order.items = []

        return order

    def _tag_items(
        self,
        order,  # type: ProductionOrder
    ):
        # type: (...) -> None

        items_to_tag = []
        tags_to_add = self.tags_to_add

        for item in order.items:
            items_to_tag.append(item)

        if len(items_to_tag) == 0:
            return

        def _inner_tag_items(
            root_order,     # type: ProductionOrder
        ):
            # type: (...) -> bool

            some_item_tagged = False
            for item_to_tag in items_to_tag:
                root_item = root_order.get_item_by_line_id(item_to_tag.get_line_id())
                for tag in tags_to_add:
                    root_item.add_tag(tag, item_to_tag.displayed_jit)
                    some_item_tagged = True

            return some_item_tagged

        self.order_changer.change_order(order.order_id, _inner_tag_items)
