# -*- coding: utf-8 -*-
import inspect
from functools import wraps

from sysactions import get_model, StopAction, show_messagebox, get_podtype, get_line_product_name
from systools import sys_log_exception

from actions.config import get_function_authorization_level_from_config
from actions.util import get_user_level, get_authorization
from actions.pos import pos_need_to_be_blocked

configurations = None


def initialize_manager_authorizations(config):
    global configurations
    configurations = config


def user_authorized_to_execute_action(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        user_data = None

        pos_id = args[0]
        try:
            function_level = get_function_authorization_level_from_config(configurations, f.func_name)
            model = get_model(pos_id)
            operator = model.find("./Operator")
            if operator is not None:
                user_id = operator.get("id")
                if get_user_level(user_id) <= function_level:
                    status, user_data = get_authorization(pos_id, function_level, model, executed_function=f.func_name)
                    if not status:
                        return StopAction()
        except BaseException as ex: # noqa
            error_message = "$GET_USER_AUTHORIZATION_ERROR_" + str(type(ex).__name__).upper()
            sys_log_exception("Error validating user authorization")
            show_messagebox(pos_id, message=error_message, icon="error")
            return False

        if 'auth_data' in inspect.getargspec(f).args:
            kwargs['auth_data'] = user_data

        return f(*args, **kwargs)

    return decorated_function


def block_action_if_pos_is_blocked(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            pos_id = args[0]
            model = get_model(pos_id)
            pod_type = get_podtype(model)
            if pod_type != 'TT' and pos_need_to_be_blocked(pos_id):
                from msgbusboundary import MsgBusTableService as tableService
                from table_actions import deselect_table
                selected_table = tableService().get_selected_table(pos_id)
                if selected_table is None:
                    deselect_table(pos_id)

                show_messagebox(pos_id, message="$POS_BLOCKED", icon="error")
                return StopAction()
        except BaseException as _: # noqa
            return False

        return f(*args, **kwargs)

    return decorated_function


def block_action_if_order_items_not_resolved(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        from posactions import list_open_options

        pos_id = args[0]
        model = get_model(pos_id)
        order = model.find("CurrentOrder/Order")

        sale_lines = order.findall("SaleLine")
        active_sale_lines = _get_active_order_lines(sale_lines)
        is_remote_order = order.find("CustomOrderProperties/OrderProperty[@key='REMOTE_ORDER_ID']")
        if not active_sale_lines and is_remote_order is None:
            show_messagebox(pos_id, "$HAS_NO_ITEMS_IN_ORDER", title="")
            return False

        option = list_open_options(order)
        if option is not None:
            prod_name = get_line_product_name(model, int(option.get("lineNumber")))
            show_messagebox(pos_id, message="$NEED_TO_RESOLVE_OPTION|%s" % (prod_name.encode("UTF-8")), icon="error")
            return False

        return f(*args, **kwargs)

    return decorated_function


def _get_order_deleted_lines(sale_lines):
    return map(lambda x: x.get("lineNumber"), filter(lambda x: x.get("level") == "0" and x.get("qty") == "0", sale_lines))


def _get_active_order_lines(sale_lines):
    deleted_line_numbers = _get_order_deleted_lines(sale_lines)

    return filter(lambda x: x.get("lineNumber") not in deleted_line_numbers, sale_lines)
