import threading

from PySide6.QtCore import Signal, Slot
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget

from PySideJZ.JZAbvs import JZAbvs
from PySideJZ.JZContainer import JZContainer


class JZPrompt(JZContainer):

    question = Signal(str, str, str)
    success = Signal(str)
    error = Signal(str)
    reset = Signal()

    class Answer:
        A = 0
        B = 1

    def __init__(self, parent: QWidget, height: int = 100):
        super().__init__(parent=parent, layout=QVBoxLayout(), spacing=1, name="NoBorder")
        self.question_label = QLabel("", self, wordWrap=True, fixedHeight=height)
        self.question_label.setAlignment(JZAbvs.Align.C)
        self.button_a = QPushButton("", self, enabled=False)
        self.button_b = QPushButton("", self, enabled=False)
        container_buttons = JZContainer(self, layout=QHBoxLayout(), spacing=1, name="NoBorder")
        container_buttons.addMultiple([self.button_a, self.button_b])
        self.addMultiple([self.question_label, container_buttons])

        self._event = threading.Event()
        self._answer = None
        self.question.connect(self._on_question)
        self.success.connect(self._on_success)
        self.error.connect(self._on_error)
        self.reset.connect(self._on_reset)
        self.reset.emit()
        self.button_a.clicked.connect(self._button_a_clicked)
        self.button_b.clicked.connect(self._button_b_clicked)

    def ask_question(self, question: str, a: str, b: str, timeout_s: int = 3) -> int:
        """Asks a question the prompt dialog and waits for the answer by using event."""
        if (not a) and (not b):
            raise ValueError("Question without possible answers")
        self._event.clear()
        self.question.emit(question, a, b)
        success = self._event.wait(timeout=timeout_s if timeout_s > 0 else None)
        if not success:
            self.reset.emit()
            raise TimeoutError("Timeout while waiting for prompt answer")
        answer = self._answer
        self._answer = None
        self._event.clear()
        self.reset.emit()
        return answer

    @Slot(str, str, str)
    def _on_question(self, question: str, a: str, b: str) -> None:
        self.question_label.setProperty("onLabelStatus", "Ongoing")
        self.question_label.style().polish(self.question_label)
        self.question_label.setText(question)

        if (not a) and (not b):
            raise ValueError("Question without possible answers")

        if a:
            self.button_a.setText(a)
            self.button_a.setEnabled(True)
        else:
            self.button_a.setText(a)
            self.button_a.setEnabled(False)

        if b:
            self.button_b.setText(b)
            self.button_b.setEnabled(True)
        else:
            self.button_b.setText(b)
            self.button_b.setEnabled(False)

    @Slot()
    def _on_reset(self) -> None:
        self.question_label.setProperty("onLabelStatus", "Info")
        self.question_label.style().polish(self.question_label)
        self.question_label.setText("")
        self._clear_buttons()
        self._event.clear()
        self._answer = None

    @Slot(str)
    def _on_success(self, text: str) -> None:
        self.question_label.setProperty("onLabelStatus", "On")
        self.question_label.style().polish(self.question_label)
        self.question_label.setText(text)
        self._clear_buttons()

    @Slot(str)
    def _on_error(self, text: str) -> None:
        self.question_label.setProperty("onLabelStatus", "Off")
        self.question_label.style().polish(self.question_label)
        self.question_label.setText(text)
        self._clear_buttons()

    @Slot()
    def _button_a_clicked(self) -> None:
        self._answer = JZPrompt.Answer.A
        self._event.set()

    @Slot()
    def _button_b_clicked(self) -> None:
        self._answer = JZPrompt.Answer.B
        self._event.set()

    def _clear_buttons(self) -> None:
        self.button_a.setText("")
        self.button_a.setEnabled(False)
        self.button_b.setText("")
        self.button_b.setEnabled(False)
