import json
from abc import abstractmethod
from xml.etree import cElementTree as eTree

from msgbus import TK_SYS_NAK

from application.model.configuration import Configurations
from application.model.customexception import ErrorApplyingBenefit
from mbcontextmessagehandler import MbContextMessageBus
from messagebus import Message, DataType
from typing import Optional
from ... import NDiscountTokens


class DefaultBenefitApplierRepository(object):

    def __init__(self, configs, message_bus):
        # type: (Configurations, MbContextMessageBus) -> None

        self.logger = configs.logger
        self.configs = configs
        self.message_bus = message_bus

    def add_benefit(
            self,
            current_pos_id,             # type: int
            benefit_id,                 # type: str
            benefit,                    # type: str
            benefit_applier,            # type: str
            tender_id,                  # type: str
            user_auth_level             # type: bool
    ):
        # type: (...) -> None

        data = json.dumps(dict(
                posId=current_pos_id,
                benefitId=benefit_id,
                benefit=benefit,
                benefit_applier=benefit_applier,
                tender_id=tender_id,
                user_auth_level=user_auth_level
        ))

        message = Message(
            token=NDiscountTokens.TK_NDISCOUNT_ADD_BENEFIT,
            data=data,
            data_type=DataType.string
        )

        response = self.message_bus.send_message("nDiscount", message)
        if response.token == TK_SYS_NAK:
            raise ErrorApplyingBenefit(response.data)

    def remove_benefit(self, current_pos_id, benefit_ids=None):
        # type: (int, Optional[str, list, None]) -> Message

        data = json.dumps(dict(pos_id=current_pos_id, benefit=benefit_ids))
        message = Message(token=NDiscountTokens.TK_NDISCOUNT_REMOVE,
                          data=data,
                          data_type=DataType.string)

        return self.message_bus.send_message("nDiscount", message)

    def apply_automatics_benefits(self, current_pos_id):
        # type: (str) -> Message

        message = Message(token=NDiscountTokens.TK_NDISCOUNT_APPLY_AUTOMATIC_BENEFITS,
                          data=json.dumps({"pos_id": current_pos_id}),
                          data_type=DataType.string)

        return self.message_bus.send_message("nDiscount", message)

    @abstractmethod
    def check_coupon_id(
        self,       # type: DefaultBenefitApplierRepository
        pos_id,     # type: int
        coupon_id,  # type: str
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def get_benefit_and_lock(self, coupon_id):
        # type: (str) -> str

        raise NotImplementedError()

    @abstractmethod
    def unlock_benefit(
        self,
        benefit_id,     # type: str
        pos_id,         # type: int
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def burn_benefit(
        self,
        benefit_id,     # type: str
        pos_id,         # type: int
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def get_benefit_info(self, data):
        # type: (str) -> None

        raise NotImplementedError()

    @abstractmethod
    def get_benefit_id_by_custom_property(self, order_picture):
        # type: (eTree) -> str

        raise NotImplementedError()
