#!/usr/bin/python3 -su

## Copyright (C) 2014 troubadour <trobador@riseup.net>
## Copyright (C) 2014 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>

"""
This script creates a GUI message dialog using PyQt5, intended to confirm downloads
and display information about currently installed and available versions.

Usage:
/usr/libexec/msgcollector/msgdispatcher_dispatch_x <message_type> <title> <installed_version> <online_versions> <message> <question> <button_type>

Arguments:
1. message_type: 'info', 'warning', or 'error'
2. title: The window title
3. installed_version: The currently installed version
4. online_versions: A comma-separated list of online available versions
5. message: The main message text
6. question: An additional question or prompt
7. button_type: 'ok' for a single OK button, 'yesno' for Yes and No buttons

Example:
/usr/libexec/msgcollector/msgdispatcher_dispatch_x warning "Update Available" "1.0" "1.1,1.2" "A new version is available." "Do you want to update?" yesno
"""

import os
import sys
import signal
import argparse
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5 import QtCore, QtGui, QtWidgets


def signal_handler(sig, frame):
    sys.exit(128 + sig)


class GuiMessage(QtWidgets.QDialog):
    def __init__(self, args):
        super(GuiMessage, self).__init__()

        self.itype = args.message_type
        self.title = args.title
        self.installed_version = args.installed_version
        self.online_versions = args.online_versions
        self.message = args.message
        self.question = args.question
        self.button = args.button_type

        self.layout = QtWidgets.QGridLayout(self)
        self.i_label = QtWidgets.QLabel(self)
        self.label = QtWidgets.QLabel(self)
        self.version_group = QtWidgets.QGroupBox(self)
        self.text = QtWidgets.QTextBrowser(self)
        self.button_box = QtWidgets.QDialogButtonBox(self)

        self.setup_ui()

    def setup_ui(self):
        idir = "/usr/share/icons/gnome-colors-common/scalable/status/"
        itype = "dialog-information.svg"
        if self.itype == "warning":
            itype = "dialog-warning.svg"
        elif self.itype == "error":
            itype = "dialog-error.svg"
        itype = os.path.join(idir, itype)

        if not os.path.exists(itype):
            print(f"INFO: The icon path '{itype}' does not exist.", file=sys.stderr)

        versions = self.online_versions.split(',')

        message = self.message + '<p>' + self.question + '</p>'

        # We use QTextBrowser with a white background.
        # Set a default (transparent) background.
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(244, 244, 244))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        self.setPalette(palette)

        self.setWindowIcon(QIcon("/usr/share/icons/icon-pack-dist/tbupdate.ico"))
        self.setWindowTitle(self.title)

        image = QtGui.QImage(itype)
        self.i_label.setPixmap(QPixmap.fromImage(image))
        self.i_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.label.setText('<p><b>Download confirmation</b></p>\
                            <p>Currently installed version: <code>%s</code></p>' % self.installed_version)
        self.label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)

        self.version_group.setTitle('Online detected version:')
        self.version_group.setMinimumSize(QtCore.QSize(0, 20 + (len(versions) * 20) + 10))

        i = 0
        for version in versions:
            self.version = QtWidgets.QRadioButton(self.version_group)
            if i == 0:
                self.version.setChecked(True)
            self.version.Name = version
            self.version.setText(version)
            self.version.setGeometry(QtCore.QRect(10, i * 20 + 20, 510, 21))
            i += 1

        self.text.setMinimumSize(530, 0)
        self.text.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.text.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.text.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
        self.text.setOpenExternalLinks(True)
        self.text.setText(message)

        if self.button == 'yesno':
            self.button_box.setStandardButtons(QtWidgets.QDialogButtonBox.Yes | QtWidgets.QDialogButtonBox.No)

            self.yes_button = self.button_box.button(QtWidgets.QDialogButtonBox.Yes)
            self.yes_button.clicked.connect(self.yes_pressed)

            self.no_button = self.button_box.button(QtWidgets.QDialogButtonBox.No)
            self.no_button.setAutoDefault(True)
            self.no_button.setDefault(True)
            self.no_button.clicked.connect(self.reject)

        elif self.button == 'ok':
            self.button_box.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
            self.ok_button = self.button_box.button(QtWidgets.QDialogButtonBox.Ok)
            self.ok_button.clicked.connect(self.accept)

        self.layout.addWidget(self.i_label, 0, 0, 0, 1)
        self.layout.addWidget(self.label, 0, 1, 1, 1)
        self.layout.addWidget(self.version_group, 1, 1, 1, 1)
        self.layout.addWidget(self.text, 2, 1, 1, 1)
        self.layout.addWidget(self.button_box, 3, 1, 1, 1)

        self.center()

        QtCore.QTimer.singleShot(0, self.setSize)

        self.exec_()

    def reject(self):
        print("65536")
        sys.exit()

    def setSize(self):
        ## Size is returned
        window_height = int((self.label.size().height()
                             + self.text.document().size().height()
                             + self.version_group.size().height() + 100))
        maximum_height = int(QtWidgets.QDesktopWidget().availableGeometry().height() - 100)
        if window_height <= maximum_height:
            self.resize(800, window_height)
            self.center()
            if self.button == 'yesno':
                self.no_button.setFocus()
            elif self.button == 'ok':
                self.ok_button.setFocus()
        else:
            self.resize(800, maximum_height)
            self.center()
            if self.button == 'yesno':
                self.no_button.setFocus()
            elif self.button == 'ok':
                self.ok_button.setFocus()

    def center(self):
        frame_geometry = self.frameGeometry()
        center_point = QtWidgets.QDesktopWidget().availableGeometry().center()
        frame_geometry.moveCenter(center_point)
        self.move(frame_geometry.topLeft())

    def yes_pressed(self):
        for version in self.version_group.findChildren(QtWidgets.QRadioButton):
            if version.isChecked():
                print(version.Name)
        sys.exit()

    def no_pressed(self):
        print("65536")
        sys.exit()


def main():
    parser = argparse.ArgumentParser(description="Create a GUI message dialog using PyQt5.")
    parser.add_argument('message_type', choices=['info', 'warning', 'error'], help="Type of the message ('info', 'warning', or 'error')")
    parser.add_argument('title', help="The window title")
    parser.add_argument('installed_version', help="The currently installed version")
    parser.add_argument('online_versions', help="Comma-separated list of online available versions")
    parser.add_argument('message', help="The main message text")
    parser.add_argument('question', help="An additional question or prompt")
    parser.add_argument('button_type', choices=['ok', 'yesno'], help="Type of the button ('ok' for a single OK button, 'yesno' for Yes and No buttons)")

    args = parser.parse_args()

    app = QtWidgets.QApplication(sys.argv)
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    timer = QtCore.QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)

    message = GuiMessage(args)
    if message is not None:
        app.exec_()


if __name__ == '__main__':
    main()
