import json
import logging
import xml.etree.cElementTree as eTree
from xml.etree import ElementTree

from discount_api.token import (
    TK_DISCOUNT_GET_JUSTIFICATION_CONFIG,
    TK_DISCOUNT_ON_TABLE_OPEN,
)

from discount_api.dto import JustificationConfigDto
from messagebus import (
    DataType,
    DefaultToken,
    Message,
    MessageBus,
    MessageBusException,
)
from typing import Optional

logger = logging.getLogger(__name__)


class DiscountService(object):
    def __init__(
        self,               # type: DiscountService
        message_bus,        # type: MessageBus
    ):
        self.message_bus = message_bus

    def on_service_open(
        self,               # type: DiscountService
        pos_id,             # type: int
        table_xml,          # type: ElementTree.Element
    ):
        # type: (...) -> Optional[int]

        data = json.dumps(
            dict(
                pos_id=pos_id,
                table_xml=eTree.tostring(
                    element=table_xml,
                    encoding="unicode",
                ),
            )
        ).encode("utf-8")

        try:
            reply = self.message_bus.send_message(
                component="nDiscount",
                message=Message(
                    token=TK_DISCOUNT_ON_TABLE_OPEN,
                    data_type=DataType.param,
                    data=data,
                    timeout=30000000,
                ),
            )

            if reply.token == DefaultToken.TK_SYS_ACK:
                if reply.data == b"":
                    return None

                return int(reply.data)

        except MessageBusException:
            logger.warning("Error applying discount on service open", exc_info=True)

        return None

    def get_justification_config(
        self,               # type: DiscountService
    ):
        # type: (...) -> JustificationConfigDto

        reply = self.message_bus.send_message(
            component="nDiscount",
            message=Message(
                token=TK_DISCOUNT_GET_JUSTIFICATION_CONFIG,
                data_type=DataType.param,
                data=b"",
                timeout=30000000,
            ),
        )

        if reply.token == DefaultToken.TK_SYS_ACK:
            reply_dict = json.loads(reply.data.decode("utf-8"))
            return JustificationConfigDto(
                justifications=reply_dict["justifications"],
            )

        try:
            data_text = reply.data.decode("utf-8")
        except UnicodeDecodeError:
            data_text = reply.data.hex()

        error_message = "Error retrieving justification config. Token: [{}], data: [{}]".format(
            reply.token,
            data_text,
        )

        raise RuntimeError(error_message)
