# -*- coding: utf-8 -*-
import json
from logging import Logger
from threading import Condition

from messagebus import MessageBus, Event, AckMessage, NakMessage
from messageprocessorutil import UuidMessageProcessor
from messagetoken import EventToken


ELECTRONIC_PAYMENT = "ELECTRONIC_PAYMENT"
DEFAULT_TITLE = "$ELECTRONIC_PAYMENT"


class DialogManager(UuidMessageProcessor):
    def parse_data(self, data, event_type):
        return data.split('|')

    def call_business(self, obj):
        self.logger.debug("obj = {}".format(obj))
        pos_id, response = obj
        if pos_id not in self._message_conditions:
            return
        cond = self._message_conditions[pos_id]
        cond.acquire()
        self._dialog_response = response
        cond.notify_all()
        cond.release()

    def format_response(self, message_bus, message, event, input_obj, result):
        message_bus.reply_message(message, AckMessage())

    def format_exception(self, message_bus, message, event, input_obj, exception):
        message_bus.reply_message(message, NakMessage(exception.message))

    def format_parse_exception(self, message_bus, message, event, data, exception):
        message_bus.reply_message(message, NakMessage(exception.message))

    def __init__(self, message_bus, logger):
        # type: (MessageBus, Logger) -> None
        super(DialogManager, self).__init__()
        self.logger = logger
        self._message_bus = message_bus
        self._message_conditions = {}
        self._dialog_response = None

    def show_message(self, pos_id, message, title=DEFAULT_TITLE):
        if not message:
            return

        data = "{}\\0{}\\0{}".format(pos_id, message, title)
        self._message_bus.publish_event(Event(EventToken.SHOW_MESSAGE, ELECTRONIC_PAYMENT, data))

    def show_question(self, pos_id, message, title=DEFAULT_TITLE, buttons="$YES|$NO"):
        self._message_bus.publish_event(Event(subject=EventToken.SHOW_QUESTION, event_type=ELECTRONIC_PAYMENT,
                                              data="{}\\0{}\\0{}\\0{}".format(pos_id, message, title, buttons)))
        self._wait_condition(pos_id)
        return self._dialog_response

    def show_choices(self, pos_id, choices, message, title=DEFAULT_TITLE):
        self._message_bus.publish_event(Event(subject=EventToken.SHOW_CHOICES, event_type=ELECTRONIC_PAYMENT,
                                              data="{}\\0{}\\0{}\\0{}".format(pos_id, message, title, json.dumps(choices))))
        self._wait_condition(pos_id)
        return self._dialog_response

    def show_input(self, pos_id, message, title=DEFAULT_TITLE, input_type="text"):
        self._message_bus.publish_event(Event(subject=EventToken.SHOW_INPUT, event_type=ELECTRONIC_PAYMENT,
                                              data="{}\\0{}\\0{}\\0{}".format(pos_id, message, title, input_type)))
        self._wait_condition(pos_id)
        return self._dialog_response

    def show_qrcode(self, pos_id, code_data, title=DEFAULT_TITLE):
        event = Event(
            subject=EventToken.SHOW_QRCODE,
            event_type=ELECTRONIC_PAYMENT,
            data="{}\\0{}\\0{}".format(pos_id, code_data, title)
        )
        self._message_bus.publish_event(event)

    def show_numpad(self, pos_id, message, title=DEFAULT_TITLE):
        self._message_bus.publish_event(Event(subject=EventToken.SHOW_NUMPAD, event_type=ELECTRONIC_PAYMENT,
                                              data="{}\\0{}\\0{}".format(pos_id, message, title)))
        self._wait_condition(pos_id)
        return self._dialog_response

    def close_dialogs(self, pos_id):
        event = Event(
            subject=EventToken.CLOSE_DIALOGS,
            event_type=ELECTRONIC_PAYMENT,
            data=str(pos_id)
        )
        self._message_bus.publish_event(event)

    def close_qrcode(self, pos_id):
        event = Event(
            subject=EventToken.CLOSE_QRCODE,
            event_type=ELECTRONIC_PAYMENT,
            data=str(pos_id)
        )
        self._message_bus.publish_event(event)

    def _wait_condition(self, pos_id):
        pos_id = str(pos_id)
        if pos_id not in self._message_conditions:
            self._message_conditions[pos_id] = Condition()

        self._message_conditions[pos_id].acquire()
        self._message_conditions[pos_id].wait()
        self._message_conditions[pos_id].release()
