from abc import ABCMeta
from typing import Dict

from _AposA8Align import AposA8Align
from _AposA8CommandType import AposA8CommandType
from _AposA8PrintLine import AposA8PrintLine
from _AposA8Helpers import (
    append_items_header,
    append_and_count_sale_items,
    APOS_DASH,
    append_coupon_fiscal_parameters,
    append_customer_name,
)
from _AposA8Constants import AposA8Constants
from printer import FiscalPrinter
from msgbus import MBEasyContext

from clichehelper import ClicheHelper

AMOUNT_TEMPLATE = "%-36s   R$%7.2f"


class AposA8FiscalPrinter(FiscalPrinter):
    __metaclass__ = ABCMeta

    def __init__(
        self,
        mb_context,                     # type: MBEasyContext
        print_customer_name,            # type: bool
        cliche_helper,                  # type: ClicheHelper
        customer_text_field,            # type: str
        coupon_fiscal_parameters,       # type: Dict[str, bool]
        font_size_withdrawal_panel,     # type: str
    ):
        # type: (...) -> None

        super(AposA8FiscalPrinter, self).__init__(
            mb_context,
            print_customer_name,
            cliche_helper,
            coupon_fiscal_parameters,
        )

        self.customer_text_field = customer_text_field
        self.font_size_withdrawal_panel = font_size_withdrawal_panel

    def print_cancel(self, posid, data):
        # not implemented
        pass

    def _append_total(self, report, order, tenders, items_amount):
        qty_total = "%-36s         %3d" % ("QTD. TOTAL DE ITENS", items_amount)
        report.append(AposA8PrintLine(AposA8Align.CENTER, qty_total, AposA8CommandType.PRINT_TEXT))

        total_amount_value = float(order.get("totalAmount")) + float(order.get("taxTotal")) + float(order.get("tip", 0))

        total_amount_text = AMOUNT_TEMPLATE % ("VALOR TOTAL R$", total_amount_value)
        report.append(AposA8PrintLine(AposA8Align.CENTER, total_amount_text, AposA8CommandType.PRINT_TEXT))

        discount_amount_value = float(order.get("discountAmount"))
        discount = AMOUNT_TEMPLATE % ("DESCONTO", discount_amount_value)
        report.append(AposA8PrintLine(AposA8Align.CENTER, discount, AposA8CommandType.PRINT_TEXT))

        total_payable = AMOUNT_TEMPLATE % ("VALOR A PAGAR", total_amount_value - discount_amount_value)
        report.append(AposA8PrintLine(AposA8Align.CENTER, total_payable, AposA8CommandType.PRINT_TEXT))

        payment = "%-36s  %s" % ("FORMA DE PAGAMENTO", "Valor Pago")
        report.append(AposA8PrintLine(AposA8Align.CENTER, payment, AposA8CommandType.PRINT_TEXT))
        for tender in tenders:
            tender_descr = self.get_payment_description(self.mb_context, tender)
            tender_amount = tender.amount + tender.change
            tender_text = AMOUNT_TEMPLATE % (tender_descr, tender_amount)
            report.append(AposA8PrintLine(AposA8Align.CENTER, tender_text, AposA8CommandType.PRINT_TEXT))

        # Get "Change" (sixth value of tender tuple) from last tender in tenders
        change = tenders[len(tenders) - 1].change
        if change > 0:
            order_voided = order.get("state") == "VOIDED"
            factor = -1 if order_voided else 1

            change_text = AMOUNT_TEMPLATE % ("Troco", change * factor)
            report.append(AposA8PrintLine(AposA8Align.CENTER, change_text, AposA8CommandType.PRINT_TEXT))

    def _append_customer_text_field(self, report):
        if self.customer_text_field != "":
            for customer_text in self.customer_text_field.split('\\n'):
                report.append(
                    AposA8PrintLine(AposA8Align.CENTER, customer_text.replace("\\n", ""), AposA8CommandType.PRINT_TEXT))
            report.append(
                AposA8PrintLine(AposA8Align.CENTER, AposA8Constants.SEPARATOR_DASH, AposA8CommandType.PRINT_TEXT))

    @staticmethod
    def _append_satisfaction_survey(report, model, satisfaction_survey_code):
        if satisfaction_survey_code is not None and model is not None:
            report.append(APOS_DASH)
            ssc = satisfaction_survey_code
            satisfaction_survey_code = '-'.join(ssc[i:i + 3] for i in range(0, len(ssc), 3))
            report.append(AposA8PrintLine(AposA8Align.CENTER, satisfaction_survey_code, AposA8CommandType.PRINT_TEXT))
            report.append(APOS_DASH)

    def _append_coupon_body(self, customer_name, model, order, report, tenders, printer_common):
        append_items_header(report)
        items_amount = append_and_count_sale_items(report, order, printer_common)
        report.append(APOS_DASH)
        self._append_total(report, order, tenders, items_amount)
        report.append(APOS_DASH)

        append_customer_name(
            model=model,
            print_customer_name=self.print_customer_name,
            report=report,
            order=order,
            customer_name=customer_name,
            font_size_withdrawal_panel=self.font_size_withdrawal_panel,
        )

        append_coupon_fiscal_parameters(
            coupon_fiscal_parameters=self.coupon_fiscal_parameters,
            report=report,
            order=order,
        )

        self._append_satisfaction_survey(report, model, self.get_satisfaction_survey_code(order))

    def _append_cliche(self, report):
        for line in self.cliche_helper.get_cliche():
            report.append(AposA8PrintLine(AposA8Align.CENTER, line, AposA8CommandType.PRINT_TEXT))
        report.append(APOS_DASH)



