from logging import Logger
from typing import (
    Optional,
    List,
)

from production.model import (
    ProductionOrder,
    Item,
)
from .._OrderChangerProductionBox import OrderChangerProductionBox


class StoredOrderUnsplitter(OrderChangerProductionBox):

    def __init__(
        self,                       # type: StoredOrderUnsplitter
        name,                       # type: str
        sons,                       # type: object
        prod_states_clean_cache,    # type: List[str]
        logger=None,                # type: Optional[Logger]
    ):
        # type: (...) -> None

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

        self.prod_states_clean_cache = prod_states_clean_cache

    def change_order(
        self,     # type: StoredOrderUnsplitter
        order,    # type: ProductionOrder
    ):
        # type: (...) -> ProductionOrder

        if not order.stored_split_order:
            return order

        self._update_cached_order(
            new_order=order
        )

        return self._get_merged_order(order=order)

    def _update_cached_order(
        self,            # type: StoredOrderUnsplitter
        new_order,       # type: ProductionOrder
    ):
        # type: (...) -> None

        if new_order.prod_state in self.prod_states_clean_cache:
            self.delete_order(order_id=new_order.order_id)
            return

        cached_order = self.get_order(order_id=new_order.order_id)
        if cached_order is None:
            self.save_order(order=new_order)
            return

        new_order.items = self._get_merged_items(
            new_order=new_order,
            cache_order=cached_order,
        )

        self.save_order(order=new_order)

    @staticmethod
    def _get_merged_items(
        new_order,      # type: ProductionOrder
        cache_order,    # type: ProductionOrder
    ):
        # type: (...) ->  List[Item]

        merged_items = cache_order.items

        items_to_remove_from_cache = []
        for cloned_item in new_order.items:
            for cached_item in merged_items:
                if cloned_item.get_line_id() == cached_item.get_line_id():
                    items_to_remove_from_cache.append(cached_item)
                    break

        for item_to_remove in items_to_remove_from_cache:
            merged_items.remove(item_to_remove)

        merged_items.extend(new_order.items)
        return merged_items

    def _get_merged_order(
        self,       # type: StoredOrderUnsplitter
        order,      # type: ProductionOrder
    ):
        # type: (...) -> ProductionOrder

        order_cloned = order.clone(items=order.items)
        split_indexes = order.order_id.split("-")
        order_cloned.order_id = "-".join(split_indexes[:len(split_indexes) - 1])

        for index in range(0, 9):
            temp_order = self.get_order(order_id="-".join([order_cloned.order_id, str(index)]))
            if temp_order:
                order_cloned.items = self._get_merged_items(
                    new_order=temp_order,
                    cache_order=order_cloned,
                )

        order_cloned.stored_split_order = False
        return order_cloned
