# -*- coding: utf-8 -*-
from msgbus import TK_POS_LISTUSERS, FM_PARAM, TK_SYS_NAK, MBEasyContext
from mw_helper import show_filtered_list_box_dialog, show_message_dialog
from old_helper import BaseRepository
from sysactions import (
    send_message,
    get_model,
    get_podtype,
    get_user_information,
    show_messagebox,
    StopAction,
    get_poslist,
)
from xml.etree import cElementTree as eTree
from userhelper import UserHelper

from .. import USECS_PER_SEC, logger

mb_context = None


def list_opened_users(pos_id):
    msg = send_message("POS%d" % int(pos_id), TK_POS_LISTUSERS, FM_PARAM, "%s" % pos_id, timeout=600 * USECS_PER_SEC)
    if msg.token == TK_SYS_NAK:
        logger.error("Logoff POS %d - Error listing logged operators" % int(pos_id))
        raise Exception("Error listing logged operators")

    model = get_model(pos_id)
    working_mode = model.find("WorkingMode").get("usrCtrlType")

    xml = eTree.XML(msg.data)
    opened_users = [tag for tag in xml.findall("User") if not tag.get("closeTime")]
    working_users = [tag for tag in opened_users if tag.get("userControlType") == working_mode]

    if working_mode == 'QSR':
        working_users = [tag for tag in working_users if tag.get("posId") == pos_id]

    return working_users


def list_all_opened_users(pos_id):
    msg = send_message("POS%d" % int(pos_id), TK_POS_LISTUSERS, FM_PARAM, "%s" % pos_id, timeout=600 * USECS_PER_SEC)

    if msg.token == TK_SYS_NAK:
        logger.error("Logoff POS %d - Error listing logged operators" % int(pos_id))
        raise Exception("Error listing logged operators")

    xml = eTree.XML(msg.data)
    opened_users = [tag for tag in xml.findall("User") if not tag.get("closeTime")]
    working_users = [tag for tag in opened_users]

    return working_users


def list_ids_opened_users():
    with UserHelper(mb_context) as user_helper:
        users_id = []
        users = user_helper.get_all_logged_users()
        for x in users:
            users_id.append(int(x))

        return users_id


def check_valid_user(pos_id, user_id):
    user_xml = get_user_information(user_id)
    if user_xml is None:
        show_message_dialog(pos_id, message="$INVALID_USER_OR_PASSWORD")
        return False

    user_list = eTree.XML(user_xml).findall("user")
    user_filter = filter(lambda x: x.get("UserId") == str(user_id), user_list)
    if user_filter in [None, [], ""]:
        show_message_dialog(pos_id, message="$INVALID_USER_OR_PASSWORD")
        return False

    return True


def get_opened_users(pos_id):
    parsed_users_options = []
    pos_user_list = []
    is_ts_listed = False
    for pos_id_to_list in sorted(get_poslist()):
        opened_users = list_opened_users(pos_id=str(pos_id_to_list),)

        if len(opened_users) > 0:
            opened_users.sort(key=lambda x: x.get("id"))
            model = get_model(posid=pos_id_to_list,)
            pod_type = get_podtype(model=model,)
            if pod_type == "TT":
                continue

            working_mode = model.find("WorkingMode").get("usrCtrlType")

            prefix = "POS{:02d}"
            if working_mode == "TS":
                if is_ts_listed:
                    continue
                is_ts_listed = True
                prefix = "TS"
            else:
                prefix = prefix.format(pos_id_to_list)

            for user in opened_users:
                parsed_users_options.append("{} - {} - {}".format(prefix, user.get('id'), user.get('name')))
                pos_user_list.append((pos_id_to_list, user))

    if len(parsed_users_options) == 0:
        show_message_dialog(pos_id, message="$THERE_ARE_NO_OPENED_USERS")
        return None, None, None

    index = show_filtered_list_box_dialog(
        pos_id=pos_id,
        options="|".join(parsed_users_options),
        title="$LOGOUT",
        message="",
        mask="NOFILTER",
    )
    if index is None:
        return None, None, None

    pos_to_close_user = pos_user_list[index][0]
    model = get_model(posid=pos_to_close_user)
    user = pos_user_list[index][1]
    operator = [op for op in model.findall("Operators/Operator") if op.get("id") == user.get("id")]
    return pos_to_close_user, user, operator[0]




def is_user_already_logged(pos_id, user_id, try_fix=True):
    params = "\0".join(["%s" % pos_id, "true"])
    msg = send_message("POS%d" % int(pos_id), TK_POS_LISTUSERS, FM_PARAM, params, timeout=600 * USECS_PER_SEC)
    if msg.token == TK_SYS_NAK:
        logger.error("Logoff POS %d - Error getting logged users" % int(pos_id))
        return True

    xml = eTree.XML(msg.data)
    opened_users = [tag for tag in xml.findall("User") if not tag.get("closeTime")]
    working_users = [tag for tag in opened_users if tag.get("id") == user_id]

    if len(working_users) > 0:
        model = get_model(pos_id)
        _user_has_same_working_mode(model, opened_users, pos_id, user_id)

        operator = [op for op in model.findall("Operators/Operator") if op.get("id") == user_id]
        if len(operator) > 0 and operator[0].get('state') == 'PAUSED':
            return False

        user_info = [x for x in opened_users if x.get("id") == user_id][0]
        old_login = model.find("PosState").get("period") != user_info.get("sessionId").split(',period=')[-1]
        if try_fix and old_login:
            _fix_opened_users(pos_id, user_id)
            return is_user_already_logged(pos_id, user_id, False)

        show_message_dialog(pos_id, message="$OPERATOR_ALREADY_LOGGED|{}".format(user_info.get("posId")))
        return True

    return False


def _user_has_same_working_mode(model, opened_users, pos_id, user_id):
    user_info = [x for x in opened_users if x.get("id") == user_id]
    if user_info:
        pos_working_mode = model.find("WorkingMode").get("usrCtrlType")
        operator_working_mode = "QSR" if "pos" in user_info[0].get("sessionId") else "TS"
        if pos_working_mode != operator_working_mode:
            show_messagebox(pos_id, "$USER_LOGGED_IN_ANOTHER_POS_TYPE|{}".format(user_info[0].get("posId")))
            raise StopAction()


def _fix_opened_users(pos_id, user_id):
    # type: (str) -> None
    def inner_func(conn):
        # type: (Connection) -> None
        query = _fix_opened_users_query.format(user_id)
        conn.query(query)

    repository = BaseRepository(mb_context)
    repository.execute_with_connection(inner_func, pos_id)


def set_context(context):
    global mb_context
    mb_context = context


_fix_opened_users_query = """
    UPDATE UserCount SET CloseTime = (
        SELECT MAX(OpenTime) FROM UserCount WHERE OperatorId = '{0}'
    ) WHERE OperatorId = '{0}' AND CloseTime is NULL AND OpenTime < (
        SELECT MAX(CloseTime) FROM UserCount WHERE OperatorId = '{0}'
    )
"""

