import logging
import sysactions

from actions.util import get_authorization
from mw_helper import show_filtered_list_box_dialog

from typing import (
    Dict,
    List,
    Optional,
    Union,
)
from xml.etree import cElementTree as eTree

logger = logging.getLogger("PosActions")


def get_tender_type(
    pos_id,             # type: str
    model,              # type: eTree.Element
    tender_type_id,     # type: str
):
    # type: (...) -> Optional[Dict[str, Union[str, int, bool]]]

    tender_type = _select_tender_type(
        pos_id=pos_id,
        tender_type_id=tender_type_id,
    )
    if tender_type is None:
        return None

    necessary_level = int(tender_type['needAuth'] or 0)
    operator_level = _get_current_operator_level(model=model)
    if necessary_level > operator_level:
        authorized = get_authorization(
            pos_id=pos_id,
            min_level=necessary_level,
            model=model,
        )[0]

        if not authorized:
            return None

    return tender_type


def get_all_tender_types():
    # type: (...) -> List[Dict[str, Union[str, int, bool]]]

    all_tender_types = sysactions.get_tender_types()
    tender_types = [tender for tender_id, tender in all_tender_types.items() if tender_id < 200]
    for tender_type in tender_types:
        tender_type["showInFC"] = True if tender_type["id"] < 90 else False
        tender_type["showInDL"] = True if 90 <= tender_type["id"] < 120 else False
        parent_id = "parentId "
        if parent_id in tender_type:
            tender_type["parentId"] = tender_type[parent_id]
            del tender_type[parent_id]

        has_child = False
        for tender_type_aux in tender_types:
            if "parentId" in tender_type_aux and tender_type_aux["parentId"] == tender_type["id"]:
                has_child = True
                break

        tender_type["hasChild"] = has_child

    try:
        tender_types = sorted(tender_types, key=lambda k: k['id'])
    except (Exception, ) as _:
        logger.exception("Error ordering tender types")

    return tender_types


def _select_tender_type(
    pos_id,             # type: str
    tender_type_id,     # type: str
):
    # type: (...) -> Optional[Dict[str, Union[str, int, bool]]]

    all_tender_types = get_all_tender_types()
    tender_types = [
        tender
        for tender in all_tender_types
        if (tender["parentId"] is not None and tender["parentId"] == int(tender_type_id))
    ]
    if len(tender_types) != 0:
        if len(tender_types) == 1:
            return tender_types[0]
        else:
            options = [tender["descr"] for tender in tender_types]
            selected_option = show_filtered_list_box_dialog(
                pos_id=pos_id,
                options=options,
                title="$SELECT_PAYMENT_TYPE",
                mask="NOFILTER",
            )
            if selected_option is None:
                return None

            tender_type_id = tender_types[selected_option]["id"]
    else:
        return [tender for tender in all_tender_types if tender["id"] == int(tender_type_id)][0]

    return [tender for tender in tender_types if tender["id"] == tender_type_id][0]


def _get_current_operator_level(
    model,  # type: eTree.Element
):
    # type: (...) -> int

    operator_level = 0
    model_operator = model.find("Operator")
    if model_operator is not None:
        operator_level = int(model_operator.get("level") or 0)

    return operator_level
