import re
import sys

from lib.helpers import timing
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import QShortcut
from ui.test_test import Test_Test


class Test_Barcodes(Test_Test):
    def __init__(self, components=None, recipe=None, step=None, pieces=None, run_once=False, reset_on_start=True, enable_override=False):
        super().__init__(components=components, recipe=recipe, step=step, pieces=pieces, run_once=run_once, reset_on_start=reset_on_start, enable_override=enable_override)
        self.barcodes_spec = {
            "serial": self.check_serial_barcode
        }
        QShortcut(QKeySequence("Return"), self).activated.connect(self.get)
        QShortcut(QKeySequence("Enter"), self).activated.connect(self.get)
        self.barcodes_le.setFocus()

    def start(self, recipe=None, step=None, pieces=None):
        show = super().start(recipe=recipe, step=step, pieces=pieces)
        if show is False:
            return show
        self.visualize()
        self.barcodes_le.setPalette(self.status_palettes[None])
        self.barcodes_le.setText("")
        self.barcodes_le.setFocus()
        # TESTING
        if "--test-barcodes" in sys.argv or "--test" in sys.argv:
            self.barcodes_le.setText("-----TEST_BARCODE-----")
            self.test_timer = QTimer()
            self.test_timer.setSingleShot(True)
            self.test_timer.timeout.connect(self.get)
            self.test_timer.start(500)
        # /TESTING
        return show

    # def stop(self):
    #     super().stop()

    def reset(self):
        super().reset()
        self.barcodes = {}

    def get(self, data=None, override=False):
        if self.done:  # avoid proccessing if completed
            return
        if data is None:
            data = self.barcodes_le.text()
        if not len(data):
            data = None
        if data is None:
            super().get(None, override=override)
            return
        barcode_ok = False
        for barcode_name, barcode_check in self.barcodes_spec.items():
            if barcode_check(data):
                self.barcodes[barcode_name] = data
                barcode_ok = True
                break
        if barcode_ok:
            self.barcodes_le.setPalette(self.status_palettes[True])
        else:
            self.barcodes_le.setPalette(self.status_palettes[False])
        self.barcodes_le.setText("")
        self.barcodes_le.setFocus()
        if len(self.barcodes_spec.keys() - self.barcodes.keys()) == 0:
            result = self.barcodes
            ok = True
        else:
            result = None
            ok = None
        super().get([{
            "time": timing(),
            "results": {
                "ok": ok,
                "result": result,
                "data": self.barcodes,
            },
        }], override=override, fail=ok is False)

    def visualize(self, data=None):
        if data is None:
            data = {}
        d = data.get("results", {}).get("data", {})
        for k, l in {
            "serial": self.serial_l,
        }.items():
            l.setText(str(d.get(k, "-")))
        super().visualize(data)

    def check_serial_barcode(self, barcode=None):
        if not isinstance(barcode, str) or len(barcode) == 0:
            return False
        barcode_regex = self.step.spec.get("serial", ".*")
        barcode_regex = barcode_regex.replace("{RECIPE}", self.recipe.name)
        for n in range(32):
            barcode_regex = barcode_regex.replace(f"{{N{n}}}", f"[0-9]{{{n}}}")
        return re.fullmatch(barcode_regex, barcode) is not None
