import sys
import re

from PyQt5.QtWidgets import QMessageBox, QInputDialog, QLineEdit, QSpacerItem, QGridLayout, QSizePolicy, QTextEdit
from PyQt5.QtCore import Qt, PYQT_VERSION_STR
from PyQt5.QtGui import QGuiApplication


class LrmMessageBox(QMessageBox):
    def exec(self):
        title = self.windowTitle()
        if title.startswith("@"):
            self.setWindowTitle(title[1:])

        for button in self.buttons():
            if button.text() == "Show Details...":
                button.clicked.connect(self.expand_detail)
                break

        self.set_width()
        QGuiApplication.setOverrideCursor(Qt.ArrowCursor)
        QMessageBox.exec(self)
        QGuiApplication.restoreOverrideCursor()

    def expand_detail(self, _dummy):
        text_edit = self.findChild(QTextEdit)
        if text_edit is not None:
            text_edit.setMinimumHeight(0)
            text_edit.setMaximumHeight(16777215)
            text_edit.setMinimumWidth(0)
            text_edit.setMaximumWidth(16777215)
            text_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        spacer = QSpacerItem(700, 200, QSizePolicy.Minimum, QSizePolicy.Expanding)
        layout: QGridLayout = self.layout()
        layout.addItem(spacer, 3, 0, 3, 3)

    def set_width(self, width=400):
        spacer = QSpacerItem(width, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
        layout: QGridLayout = self.layout()
        layout.addItem(spacer, 3, 0, 0, 3)


class DialogWrapper:
    def __init__(self, parent, title_prefix = None):
        self.parent = parent  # parent window
        self.title_prefix = title_prefix  # string to be add to title

    def about(self, msg, parent=None, title="@About", spec_versions=None):
        if self is not None:
            parent, title = self.get_params(parent, title)
        tmp = re.search("([0-9]+\.[0-9]+\.[0-9]+)", sys.version).groups()[0]
        # msg += F"\n\nPython {tmp}\nQt {Qt .version().toString()}"
        msg += F"\n\nPython {tmp}\nPyQt {PYQT_VERSION_STR}"
        if spec_versions:
            msg += f"\n{spec_versions}"
        LrmMessageBox.about(parent, title, msg)

    def confirm(self, msg, parent=None, title="@Confirmation"):
        if self is not None:
            parent, title = self.get_params(parent, title)
        QGuiApplication.setOverrideCursor(Qt.ArrowCursor)
        button = LrmMessageBox.question(parent, title, msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        QGuiApplication.restoreOverrideCursor()
        return button == QMessageBox.Yes

    #def critical(self, msg, parent=None, title="Critical"):
    #    if self is not None:
    #        parent, title = self.get_params(parent, title)
    #    QGuiApplication.setOverrideCursor(Qt.ArrowCursor)
    #    QMessageBox.critical(parent, title, msg)
    #    QGuiApplication.restoreOverrideCursor()

    def error(self, msg, detail=None, parent=None, title="@Error", icon=QMessageBox.Critical):
        DialogWrapper.message(self, msg, detail=detail, parent=parent, title=title, icon=icon)

    @staticmethod
    def exec(box: QMessageBox):
        box.exec()

    def get_params(self, parent, title):
        if parent is None:
            parent = self.parent
        if self.title_prefix is not None:
            if title.startswith("@"):
                title = title[1:]
            else:
                title = self.title_prefix + title
        return parent, title

    def input_item(self, msg, values, parent=None, title="@Select value", default=0):
        if self is not None:
            parent, title = self.get_params(parent, title)
        if title.startswith("@"):
            title = title[1:]
        QGuiApplication.setOverrideCursor(Qt.ArrowCursor)
        result = QInputDialog.getItem(parent, title, msg, values, default, False)
        QGuiApplication.restoreOverrideCursor()
        return result

    def input_long_text(self, msg, parent=None, title="@Enter multi line value", default=""):
        if self is not None:
            parent, title = self.get_params(parent, title)
        if title.startswith("@"):
            title = title[1:]
        QGuiApplication.setOverrideCursor(Qt.ArrowCursor)
        result = QInputDialog.getMultiLineText(parent, title, msg, default )
        QGuiApplication.restoreOverrideCursor()
        return result

    def input_text(self, msg, parent=None, title="@Enter value", default=""):
        if self is not None:
            parent, title = self.get_params(parent, title)
        if title.startswith("@"):
            title = title[1:]
        QGuiApplication.setOverrideCursor(Qt.ArrowCursor)
        result = QInputDialog.getText(parent, title, msg, QLineEdit.Normal, default)
        QGuiApplication.restoreOverrideCursor()
        return result

    def message(self, msg, detail=None, parent=None, title="@Information", icon=QMessageBox.Information):
        if self is not None:
            parent, title = self.get_params(parent, title)
        box = LrmMessageBox(icon, title, msg, parent=parent, buttons=QMessageBox.Ok)
        if detail is not None:
            box.setDetailedText(detail)
        box.setTextInteractionFlags(Qt.TextSelectableByMouse)
        box.exec()

    def message_file(self, filename, parent=None, title="@Information"):
        msg = ""
        with open(filename, "r") as f:
            msg = f.read()
        DialogWrapper.message(self, msg, parent=parent, title=title)

    def not_implemented(self, feature):
        msg = feature + "\n\nNot implemented yet."
        DialogWrapper.message(self, msg, title="")

    def warning(self, msg, detail=None, parent=None, title="@Warning", icon=QMessageBox.Warning):
        DialogWrapper.message(self, msg, detail=detail, parent=parent, title=title, icon=icon)

