import re

from datetime import datetime

from production.box._OrderChangerProductionBox import OrderChangerProductionBox
from production.model import Item, ProductionOrder


class AllDoneBlinkBox(OrderChangerProductionBox):
    def __init__(self, name, sons, logger=None):
        super(AllDoneBlinkBox, self).__init__(name, sons, logger)
        self.done_tags = ["done", "no-cook", "dont-need-cook"]

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

        for item in order.items:
            if not self._verify_item_tags(item):
                return order

        order.tagged_timestamp = self._get_last_done_timestamp(order)
        return order

    def _verify_item_tags(self, item):
        # type: (Item) -> bool

        if item.item_type == "COMBO":
            for son in item.items:
                if not self._verify_item_tags(son):
                    return False
        else:
            if item.voided:
                return True

            if not self._has_done_tags(item):
                return False

        return True

    def _has_done_tags(self, item):
        # type: (Item) -> bool

        has_generic_done_tag = any(x in item.tags for x in self.done_tags)
        if not item.displayed_jit or has_generic_done_tag:
            return has_generic_done_tag

        item_jit_line = item.jit_lines
        for jit in item.displayed_jit:
            if jit not in item_jit_line:
                continue

            jit_index = 0
            blink_sequence_jit = re.split('[><$]', item_jit_line)
            for jit_elem in blink_sequence_jit:
                if jit in re.findall('(\\w+)', jit_elem):
                    break
                jit_index += 1

            previous_jit_sequences = blink_sequence_jit[:jit_index]
            if not previous_jit_sequences:
                return False

            previous_jit_string = re.split('[><$]', "+".join(previous_jit_sequences))[-1]
            previous_jit_sequences = re.findall('\\w+', previous_jit_string)
            for jit_elem in previous_jit_sequences:
                if not self._part_code_is_done_in_jit(jit_elem, item):
                    return False

        return True

    @staticmethod
    def _part_code_is_done_in_jit(previous_jit, item):
        # type: (str, Item) -> bool

        return any([k for k, v in item.tags.iteritems() if v == "done-{}".format(previous_jit.lower())])

    def _get_last_done_timestamp(self, order):
        last_done = None
        for item in order.items:
            item_done = item.get_last_tag_list_time(self.done_tags)
            if item_done is None:
                continue
            if last_done is None or last_done < item_done:
                last_done = item_done
        if last_done is not None:
            return last_done.isoformat()
        return None
