from logging import Logger

from production.model import Item
from typing import (
    Dict,
    Optional,
    Union,
    List,
)
from ._OrderChangerProductionBox import OrderChangerProductionBox
from ._ProductionBox import ProductionBox


class CollapseSameItemsBox(OrderChangerProductionBox):
    def __init__(self, name, sons, include_seats, logger=None):
        # type: (str, Optional[Union[List[ProductionBox]], ProductionBox], bool, Logger) -> None

        super(CollapseSameItemsBox, self).__init__(name, sons, logger)

        self.include_seats = include_seats

    def change_order(self, order):
        new_items = []
        collapsed_items = {}  # type: Dict[str, Item]
        for item in order.items:
            key = self.build_item_key(item)
            if key not in collapsed_items:
                collapsed_items[key] = item
                if not hasattr(item, 'joined_items'):
                    item.joined_items = []

                new_items.append(item)
            else:
                self._update_collapsed_sons_quantities(
                    collapsed_item=collapsed_items[key],
                    item=item,
                )

        order.items = new_items
        return order

    def _update_collapsed_sons_quantities(
        self,               # type: CollapseSameItemsBox
        collapsed_item,     # type: Item
        item,               # type: Item
    ):
        # type: (...) -> None

        collapsed_item.qty += item.qty
        collapsed_item.multiplied_qty += item.multiplied_qty
        collapsed_item.joined_items.append(item)

        for collapsed_son in collapsed_item.items:
            for son in item.items:
                if collapsed_son.part_code == son.part_code and collapsed_son.level == son.level:
                    self._update_collapsed_sons_quantities(
                        collapsed_item=collapsed_son,
                        item=son,
                    )

    def build_item_key(self, item, key="", is_parent_product=False):
        # type: (Item, str, bool) -> str

        key += str(item.part_code)
        if self.include_seats:
            key += item.seat

        if len(item.comments) > 0:
            for comment in item.comments.values():
                key += comment.text

        if is_parent_product:
            key += str(item.qty)

        for tag in item.get_tags():
            key += tag

        for son in item.items:
            is_parent_product = item.item_type.upper() == "PRODUCT"
            key += self.build_item_key(son, key, is_parent_product=is_parent_product)

        return key
