import os
import platform
import subprocess
import sys
import traceback

from PyQt5.QtWidgets import QMessageBox

from .component import Component

if platform.system() == "Windows":
    import win32print


class Os_Label_Printer(Component):
    def __init__(self, config=None, name=None):
        super().__init__(config=config, name=name, threaded=False)
        self.simulate = False
        if "--sim-os-label-printer" in sys.argv:
            self.simulate = True

    def config_changed(self):
        self.platform = self.config[self.name]["platform"]
        # for windows:
        # cmd
        # wmic printer list brief
        # powershell
        # Get-Printer
        # for cups (linux, osx)
        # lpstat -p -d
        self.printer = self.config[self.name]["printer"]

    @Component.reconfig_on_error
    def print_label(self, template, context=None):
        if context is None:
            context = {}
        # LOAD LABEL TEMPLATE
        with open(f"config/label_templates/{str(template)}", "r", errors="surrogateescape", encoding='iso-8859-1') as f:
            label_file_contents = f.read()
        # LABEL PRINT
        #label = label.format(**context)
        label_file_contents = label_file_contents.replace("{BCODE}", "{YY}{MO}{DD}{HH}{MI}{SN6}")
        for key, val in context.items():
            key = "{" + key + "}"
            label_file_contents = label_file_contents.replace(key, val)
        if platform.system() == "Windows":
            try:
                printer = win32print.OpenPrinter(self.printer)
                job = win32print.StartDocPrinter(printer, 1, ("label", None, "RAW"))
                win32print.WritePrinter(printer, bytes(label_file_contents, encoding="utf8", errors="surrogateescape"))
                win32print.EndPagePrinter(printer)
                return label_file_contents
            except Exception as e:
                self.log.exception(traceback.format_exc())
                QMessageBox.critical(
                    None,
                    "Errore Stampante",
                    f"Non e stato possibile stampare l'etichetta.\n\nErrore:\n{e}"
                )
                return None
        else:
            try:
                os.makedirs("tmp", exist_ok=True)
                label_file = "tmp/label.prn"
                with open(label_file, "w", errors="surrogateescape") as f:
                    f.write(label_file_contents)
                if self.platform == "windows":
                    cmd = f'print /d:"{self.printer}" "{label_file}"'
                elif self.platform == "cups":
                    cmd = f'lp -d "{self.printer}" "{label_file}"'
                else:
                    raise NotImplementedError(f"platform {self.platform!r} is not supported")
                if not self.simulate:
                    p = subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True)  # unsafe
                    if p.returncode != 0:
                        self.log.exception(f"failed to print: returncode: {p.returncode}\noutput:\n{p.stdout}")
                        QMessageBox.critical(
                            None,
                            "Errore Stampante",
                            f"Non e stato possibile stampare l'etichetta.\n\nErrore:\nreturncode: {p.returncode}\noutput:\n{p.stdout}"
                        )
                        return None
                return label_file_contents
            except Exception as e:
                self.log.exception(traceback.format_exc())
                QMessageBox.critical(
                    None,
                    "Errore Stampante",
                    f"Non e stato possibile stampare l'etichetta.\n\nErrore:\n{e}"
                )
                return None
        return None
