import os.path
import sys
import weakref

from PyQt5 import QtSvg
from PyQt5.QtCore import Qt

from lib.helpers import timing
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QKeySequence, QPixmap
from PyQt5.QtWidgets import QShortcut, QApplication, QVBoxLayout
from ui.test_test import Test_Test
from lxml import etree


class Test_Instructions(Test_Test):
    def __init__(self, components=None, recipe=None, step=None, run_once=False, reset_on_start=False, enable_override=True,bench_name="generic"):
        super().__init__(components=components, recipe=recipe, step=step, run_once=run_once, reset_on_start=reset_on_start, enable_override=enable_override)
        self.bench_name = bench_name
        self.recipe=recipe
        self.svgWidget=None
        self.svg_root=None
        self.flag=False
        self.inputs={}
        self.svg_widget=QtSvg.QSvgWidget()
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.svg_widget)
        self.svg_w.setLayout(self.layout)
        self.svg_path=os.path.join("config","instruction_images",self.bench_name,"")
        self.timer = QTimer()
        self.timer.timeout.connect(self.toggle_icons)

    def start(self, recipe=None, step=None, pieces=None):
        show = super().start(recipe=recipe, step=step)

        self.timer.start(1000)
        # setup test loop
        self.get_connection = self.components["digital_io"].out.connect(self.get)

        if step is not None:
            svg_path=f"{self.svg_path}{self.recipe}.svg"
            if not os.path.exists(svg_path):
                svg_path=f"{self.svg_path}DEFAULT.svg"
            self.svg_root = etree.parse(svg_path)
            self.svg_str = etree.tostring(self.svg_root)
            self.svg_str=etree.tostring(self.svg_root)

        self.monitored_ids=self.svg_root.xpath(f'''.//*[starts-with(@id, 'sensor_')]''')

        self.tape_ids=self.svg_root.xpath(f'''.//*[starts-with(@id, 'tape_')]''')

        self.done = False
        return show

    def toggle_icons(self):
        self.flag = not self.flag

        for elem in self.tape_ids:
            if self.flag:
                self.show_tape(elem)
            else:
                self.hide_tape(elem)

        for elem in self.monitored_ids:
            sensor_index = int(elem.attrib['id'].split("_")[1]) - 3
            if self.inputs[sensor_index]:
                self.show_ok(elem)
                self.show_icon(elem)
            else:
                self.show_ko(elem)
                if self.flag:
                    self.show_icon(elem)
                else:
                    self.hide_icon(elem)

        self.show_svg()

    def show_ok(self,id):
        id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/ok.png"
    def show_ko(self,id):
        id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/arw-yel-down.png"

    def show_icon(self,id):
        id.set("display", "inline")

    def hide_icon(self,id):
            id.set("display", "none")

    def show_tape(self,id):
        id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/tape_black.png"
        id.set("display", "inline")

    def hide_tape(self,id):
        id.set("display", "none")

    def show_svg(self):
        self.svg_str = etree.tostring(self.svg_root)
        self.svg_widget.load(self.svg_str)
        QApplication.processEvents()

    def get(self, data=None, override=False):

        if self.done:  # avoid proccessing if completed
            return
        if data is None:
            super().get(None, override=override)
            return

        #check if all sensor are ok
        ok = True
        if len(data[0]["digital_io"])==0:
            return
        for sensor in self.monitored_ids:
            sensor_index = int(sensor.attrib['id'].split("_")[1])-3
            byte_idx=int(sensor_index/8)
            bit_idx=sensor_index%8
            if data[0]["digital_io"][byte_idx][bit_idx]:
                self.inputs[sensor_index] = True
            else:
                self.inputs[sensor_index] = False
                ok = False
        if ok:
            super().get([{
                "time": timing(),
                "results": {
                    "ok": ok,
                },
            }], override=override, fail=ok is False, skip_delay=False)

    def set_done(self):
        self.done=True
        self.done_ok=True


    def stop(self):
        #self.done=True
        #self.done_ok = True
        self.timer.stop()
        super().stop()

    def reset(self):
        super().reset()
