from typing import Optional, Union, List, Dict

from ._Comment import Comment
from ._CustomStorage import CustomStorage
from ._Item import Item
from ._ProdStates import ProdStates
from ._ProductionOrder import ProductionOrder
from ._StateEvent import StateEvent
from ._TagEvent import TagEvent
from ._TagEventType import TagEventType
from ._User import User
from ._Course import Course
from ._ProductionModelJsonEncoder import ProductionModelJsonEncoder
from ._ProductionExceptions import (
    TagNotFoundException,
    EventNotFoundException,
    PrinterNameFoundException,
    ViewNameFoundException,
    CommandNotFoundException,
    BuilderNotFoundException,
    ReprocessTimeNotFoundException,
    NoBoxesConfiguredException,
    NoViewsConfiguredException,
    ReprocessInvalidTimeException,
    PickListOrderNotFoundException,
    InvalidOrderToPrint,
    JitNotFoundException,
)
from ._PicklistCleanerManagerConfig import PicklistCleanerManagerConfig


def find_order_item(order, item):
    # type: (ProductionOrder, Union[Item, str]) -> Optional[Item]
    if isinstance(item, Item):
        line_id = item.get_line_id()
    else:
        line_id = item
    for item in order.items:
        if item.get_line_id() == line_id:
            return item
    return None


def get_current_line_id(line):
    return str(line.line_number) + "-" + line.item_id + "-" + str(int(line.level)) + "-" + str(line.part_code)


def has_tag(tags, line_id, tag):
    # type: (Dict, str, str) -> bool
    return line_id in tags and tag in tags[line_id]


def add_tag(tags, line_id, tag):
    # type: (Dict[str, List[str]], str, str) -> None
    if line_id in tags:
        tags[line_id].append(tag)
    else:
        tags[line_id] = [tag]


def create_states_from_state(state):
    state_order = ["IN_PROGRESS", "STORED", "TOTALED", "PAID", "VOIDED", "ABANDONED"]

    states = []

    try:
        index = state_order.index(state)
        for state in state_order[index:]:
            states.append(state)
    except ValueError:
        pass

    return states


def is_product(item):
    # type: (Item) -> bool
    return item.item_type in ("PRODUCT", "CANADD")
