from logging import Logger

from production.box import ProductionBox
from production.command import ProductionCommandProcessor
from production.manager import PublishScheduler, OrderChanger, StatisticUpdater
from production.repository import ProductRepository
from production.treebuilder import BoxConfiguration
from production.treebuilder.boxfactory.builder import (
    OrderStateFilterBoxBuilder,
    OrderSubTypeFilterBoxBuilder,
    JitItemFilterBoxBuilder,
    HideOptionBoxBuilder,
    AllDoneBlinkBoxBuilder,
    ComboDoneWhenAllDoneBoxBuilder,
    OrderSequencerBoxBuilder,
    RemoveDoingWhenDoneBoxBuilder,
    OrderStateTimerBoxBuilder,
    FromOrderStateFilterBoxBuilder,
    CustomParamCourseBoxBuilder,
    CustomParamPrepTimeBoxBuilder,
    ShowOnKitchenFilterBoxBuilder,
    NoJitAddTagBoxBuilder,
    ItemPropertiesFilterBoxBuilder,
    AllServedItemsBoxBuilder,
    SendMomentTimerBuilder,
    ConditionBoxBuilder,
    CFHHiderBoxBuilder,
    CustomPropertyFilterBoxBuilder,
    ComboFilterBoxBuilder,
    DistributorBoxBuilder,
    OrderRoundRobinBoxBuilder,
    RemoveDeletedItemsBoxBuilder,
    FilterDeletedItemsBeforeFirstStateBoxBuilder,
    OrderSpreaderBoxBuilder,
    OrderStampBoxBuilder,
    OrderMergerBoxBuilder,
    RecalledOrderStampBoxBuilder,
    ComboServedWhenAllServedBoxBuilder,
    FilterOrderIfNotAllItemsHaveTagBoxBuilder,
    AllItemsDoneBoxBuilder,
    RemoveReprocessedOrdersBoxBuilder,
    ProductCodeFilterBoxBuilder,
    OrderProductCategoryFilterBoxBuilder,
    PodTypeFilterBoxBuilder,
    SaleTypeFilterBoxBuilder,
    SkipCourseBoxBuilder,
    CollapseSameItemsBoxBuilder,
    StampItemsViewBoxBuilder,
    ItemSequencerBoxBuilder,
    StatisticBoxBuilder,
    AddTimeTagBoxBuilder,
    ProdStateFilterBoxBuilder,
    CustomPropertyValueFilterBoxBuilder,
    ItemSorterBoxBuilder,
    DisplayTimeFilterBoxBuilder,
    ProdStateTimerBoxBuilder,
    DecreaseTimeTagBoxBuilder,
    AllItemHasAtLeastOneTagFilterBoxBuilder,
    FilterOrderIfAllItemsHaveTagBoxBuilder,
    FilterOrderIfAtLeastOneItemHasAtLeastOneTagFilterBoxBuilder,
    ComboTaggedWhenAllHasTagBoxBuilder,
    SorterBoxBuilder,
    TagItemsWhenProdStateBoxBuilder,
    FilterDefaultQuantityIngredientsBoxBuilder,
    JitAddTagBoxBuilder,
    ReprocessOrdersBoxBuilder,
    JitSequencerItemFilterBoxBuilder,
    SequencerTagItemBoxBuilder,
    OrderSplitterBoxBuilder,
    OrderPropertiesFilterBoxBuilder,
    NotShowOnKitchenAddTagBoxBuilder,
    OrderUnsplitterBoxBuilder,
    FilterDeletedItemsNotSentToKitchenBoxBuilder,
    NonComboFilterBoxBuilder,
    ItemCustomParamsFilterBoxBuilder,
    NonValidJitAddTagBoxBuilder,
)

from production.view import ProductionView
from typing import Dict

from .builder import TagFilterBoxBuilder, ViewBoxBuilder


class ProductionBoxFactory(object):

    def __init__(
        self,                   # type: ProductionBoxFactory
        command_processor,      # type: ProductionCommandProcessor
        publish_scheduler,      # type: PublishScheduler
        order_changer,          # type: OrderChanger
        statistic_updater,      # type: StatisticUpdater
        product_repository,     # type: ProductRepository
        loggers,                # type: Dict[unicode, Logger]
    ):
        # type: (...) -> None

        self.command_processor = command_processor
        self.publish_scheduler = publish_scheduler
        self.order_changer = order_changer
        self.product_repository = product_repository
        self.loggers = loggers

        self.builders = {
            u"TagFilterBox": TagFilterBoxBuilder(loggers),
            u"OrderStateFilterBox": OrderStateFilterBoxBuilder(product_repository, loggers),
            u"OrderSubTypeFilterBox": OrderSubTypeFilterBoxBuilder(product_repository, loggers),
            u"JitItemFilterBox": JitItemFilterBoxBuilder(product_repository, loggers),
            u"HideOptionBox": HideOptionBoxBuilder(product_repository, loggers),
            u"ComboDoneWhenAllDoneBox": ComboDoneWhenAllDoneBoxBuilder(loggers),
            u"ComboServedWhenAllServedBox": ComboServedWhenAllServedBoxBuilder(loggers),
            u"AllDoneBlinkBox": AllDoneBlinkBoxBuilder(loggers),
            u"OrderSequencerBox": OrderSequencerBoxBuilder(product_repository, loggers),
            u"RemoveDoingWhenDoneBox": RemoveDoingWhenDoneBoxBuilder(loggers),
            u"OrderStateTimerBox": OrderStateTimerBoxBuilder(loggers),
            u"FromOrderStateFilterBox": FromOrderStateFilterBoxBuilder(product_repository, loggers),
            u"CustomParamCourseBox": CustomParamCourseBoxBuilder(product_repository, publish_scheduler, loggers),
            u"CFHHiderBox": CFHHiderBoxBuilder(product_repository, loggers),
            u"ComboFilterBox": ComboFilterBoxBuilder(
                product_repository=product_repository,
                loggers=loggers,
            ),
            u"DistributorBox": DistributorBoxBuilder(loggers),
            u"CustomParamPrepTimeBox": CustomParamPrepTimeBoxBuilder(product_repository, publish_scheduler, loggers),
            u"ShowOnKitchenFilterBox": ShowOnKitchenFilterBoxBuilder(
                product_repository=product_repository,
                loggers=loggers
            ),
            u"NotShowOnKitchenAddTagBox": NotShowOnKitchenAddTagBoxBuilder(
                product_repository=product_repository,
                loggers=loggers
            ),
            u"NoJitAddTagBox": NoJitAddTagBoxBuilder(product_repository, loggers),
            u"ItemPropertiesFilterBox": ItemPropertiesFilterBoxBuilder(loggers),
            u"AllServedItemsBox": AllServedItemsBoxBuilder(loggers),
            u"SendMomentTimerBox": SendMomentTimerBuilder(loggers),
            u"ConditionBox": ConditionBoxBuilder(loggers),
            u"CustomPropertyFilterBox": CustomPropertyFilterBoxBuilder(loggers),
            u"OrderRoundRobinBox": OrderRoundRobinBoxBuilder(order_changer, loggers),
            u"RemoveDeletedItemsBox": RemoveDeletedItemsBoxBuilder(loggers),
            u"FilterDeletedItemsBeforeFirstStateBox": FilterDeletedItemsBeforeFirstStateBoxBuilder(loggers),
            u"OrderSpreaderBox": OrderSpreaderBoxBuilder(loggers),
            u"OrderStampBox": OrderStampBoxBuilder(loggers),
            u"OrderMergerBox": OrderMergerBoxBuilder(loggers),
            u"RecalledOrderStampBox": RecalledOrderStampBoxBuilder(loggers),
            u"FilterOrderIfNotAllItemsHaveTagBox": FilterOrderIfNotAllItemsHaveTagBoxBuilder(loggers),
            u"AllItemsDoneBox": AllItemsDoneBoxBuilder(loggers),
            u"RemoveReprocessedOrdersBox": RemoveReprocessedOrdersBoxBuilder(
                command_processor=command_processor,
                loggers=loggers,
            ),
            u"ProductCodeFilterBox": ProductCodeFilterBoxBuilder(loggers),
            u"OrderProductCategoryFilterBox": OrderProductCategoryFilterBoxBuilder(loggers),
            u"PodTypeFilterBox": PodTypeFilterBoxBuilder(loggers),
            u"SaleTypeFilterBox": SaleTypeFilterBoxBuilder(loggers),
            u"SkipCourseBox": SkipCourseBoxBuilder(loggers),
            u"CollapseSameItemsBox": CollapseSameItemsBoxBuilder(loggers),
            u"ItemSequencerBox": ItemSequencerBoxBuilder(order_changer, loggers),
            u"StatisticBox": StatisticBoxBuilder(statistic_updater, loggers),
            u"AddTimeTagBox": AddTimeTagBoxBuilder(loggers),
            u"ProdStateFilterBox": ProdStateFilterBoxBuilder(product_repository, loggers),
            u"CustomPropertyValueFilterBox": CustomPropertyValueFilterBoxBuilder(loggers),
            u"ItemSorterBox": ItemSorterBoxBuilder(product_repository, loggers),
            u"SorterBox": SorterBoxBuilder(product_repository, loggers),
            u"DisplayTimeFilterBox": DisplayTimeFilterBoxBuilder(loggers),
            u"ProdStateTimerBox": ProdStateTimerBoxBuilder(loggers),
            u"DecreaseTimeTagBox": DecreaseTimeTagBoxBuilder(loggers),
            u"AllItemHasAtLeastOneTagFilterBox": AllItemHasAtLeastOneTagFilterBoxBuilder(loggers),
            u"FilterOrderIfAtLeastOneItemHasAtLeastOneTagFilterBox": FilterOrderIfAtLeastOneItemHasAtLeastOneTagFilterBoxBuilder(loggers),  # noqa
            u"ComboTaggedWhenAllHasTagBox": ComboTaggedWhenAllHasTagBoxBuilder(loggers),
            u"TagItemsWhenProdStateBox": TagItemsWhenProdStateBoxBuilder(loggers),
            u"FilterOrderIfAllItemsHaveTagBox": FilterOrderIfAllItemsHaveTagBoxBuilder(loggers),
            u"FilterDefaultQuantityIngredientsBox": FilterDefaultQuantityIngredientsBoxBuilder(loggers),
            u"JitAddTagBox": JitAddTagBoxBuilder(product_repository, loggers),
            u"ReprocessOrdersBox": ReprocessOrdersBoxBuilder(publish_scheduler, loggers),
            u"JitSequencerItemFilterBox": JitSequencerItemFilterBoxBuilder(product_repository, loggers),
            u"SequencerTagItemBox": SequencerTagItemBoxBuilder(loggers),
            u"OrderSplitterBox": OrderSplitterBoxBuilder(order_changer, publish_scheduler, loggers),
            u"OrderPropertiesFilterBox": OrderPropertiesFilterBoxBuilder(order_changer, loggers),
            u"OrderUnsplitterBox": OrderUnsplitterBoxBuilder(loggers=loggers),
            u"FilterDeletedItemsNotSentToKitchenBox": FilterDeletedItemsNotSentToKitchenBoxBuilder(loggers=loggers),
            u"NonComboFilterBox": NonComboFilterBoxBuilder(loggers=loggers),
            u"ItemCustomParamsFilterBox": ItemCustomParamsFilterBoxBuilder(
                product_repository=self.product_repository,
                loggers=loggers
            ),
            u"NonValidJitAddTagBox": NonValidJitAddTagBoxBuilder(loggers=loggers)
        }

    def set_views(self, views):
        # type: (Dict[str, ProductionView]) -> None
        self.builders[u"ViewBox"] = ViewBoxBuilder(self.command_processor, self.order_changer, views, self.loggers)
        self.builders[u"StampItemsView"] = StampItemsViewBoxBuilder(self.order_changer, views, self.loggers)

    def build(self, config):
        # type: (BoxConfiguration) -> ProductionBox
        if config.type not in self.builders:
            raise Exception("Builder not found for box: {} - {}".format(config.name, config.type))

        return self.builders[config.type].build(config)
