# SPDX-License-Identifier: LGPL-2.1-or-later
# SPDX-FileCopyrightText: 2022 FreeCAD Project Association
# SPDX-FileNotice: Part of the AddonManager.

################################################################################
#                                                                              #
#   This addon is free software: you can redistribute it and/or modify         #
#   it under the terms of the GNU Lesser General Public License as             #
#   published by the Free Software Foundation, either version 2.1              #
#   of the License, or (at your option) any later version.                     #
#                                                                              #
#   This addon is distributed in the hope that it will be useful,              #
#   but WITHOUT ANY WARRANTY; without even the implied warranty                #
#   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                    #
#   See the GNU Lesser General Public License for more details.                #
#                                                                              #
#   You should have received a copy of the GNU Lesser General Public           #
#   License along with this addon. If not, see https://www.gnu.org/licenses    #
#                                                                              #
################################################################################

"""GUI functions for uninstalling an Addon or Macro."""

import addonmanager_freecad_interface as fci
from Widgets.addonmanager_utility_dialogs import MessageDialog

# Get whatever version of PySide we can
try:
    from PySide import QtCore, QtWidgets  # Use the FreeCAD wrapper
except ImportError:
    try:
        from PySide6 import QtCore, QtWidgets  # Outside FreeCAD, try Qt6 first
    except ImportError:
        from PySide2 import QtCore, QtWidgets  # Fall back to Qt5

from addonmanager_uninstaller import AddonUninstaller, MacroUninstaller
import addonmanager_utilities as utils

translate = fci.translate


class AddonUninstallerGUI(QtCore.QObject):
    """User interface for uninstalling an Addon: asks for confirmation, displays a progress dialog,
    displays completion and/or error dialogs, and emits the finished() signal when all work is
    complete."""

    finished = QtCore.Signal()

    def __init__(self, addon_to_remove):
        super().__init__()
        self.addon_to_remove = addon_to_remove
        if hasattr(self.addon_to_remove, "macro") and self.addon_to_remove.macro is not None:
            self.uninstaller = MacroUninstaller(self.addon_to_remove)
        else:
            self.uninstaller = AddonUninstaller(self.addon_to_remove)
        self.uninstaller.success.connect(self._succeeded)
        self.uninstaller.failure.connect(self._failed)
        self.worker_thread = QtCore.QThread()
        self.worker_thread.setObjectName("AddonUninstallerGUI worker thread")
        self.uninstaller.moveToThread(self.worker_thread)
        self.uninstaller.finished.connect(self.worker_thread.quit)
        self.worker_thread.started.connect(self.uninstaller.run)
        self.progress_dialog = None
        self.dialog_timer = QtCore.QTimer()
        self.dialog_timer.timeout.connect(self._show_progress_dialog)
        self.dialog_timer.setSingleShot(True)
        self.dialog_timer.setInterval(1000)  # Can override from external (e.g. testing) code

    def run(self):
        """Begin the user interaction: asynchronous, only blocks while showing the initial modal
        confirmation dialog."""
        ok_to_proceed = self._confirm_uninstallation()
        if not ok_to_proceed:
            self._finalize()
            return

        self.dialog_timer.start()
        self._run_uninstaller()

    def _confirm_uninstallation(self) -> bool:
        """Present a modal dialog asking the user if they really want to uninstall. Returns True to
        continue with the uninstallation, or False to stop the process."""
        confirm = MessageDialog.show_modal(
            MessageDialog.DialogType.QUESTION,
            "AddonManager_ConfirmUninstallDialog",
            translate("AddonsInstaller", "Confirm remove"),
            translate("AddonsInstaller", "Are you sure you want to uninstall {}?").format(
                self.addon_to_remove.display_name
            ),
            QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel,
        )
        return confirm == QtWidgets.QMessageBox.Yes

    def _show_progress_dialog(self):
        self.progress_dialog = QtWidgets.QMessageBox(
            QtWidgets.QMessageBox.NoIcon,
            translate("AddonsInstaller", "Removing Addon"),
            translate("AddonsInstaller", "Removing {}").format(self.addon_to_remove.display_name)
            + "...",
            QtWidgets.QMessageBox.Cancel,
            parent=utils.get_main_am_window(),
        )
        self.progress_dialog.setObjectName("AddonManager_RemovingAddonDialog")
        self.progress_dialog.rejected.connect(self._cancel_removal)
        self.progress_dialog.show()

    def _run_uninstaller(self):
        self.worker_thread.start()

    def _cancel_removal(self):
        """Ask the QThread to interrupt. Probably has no effect, most of the work is in a single OS
        call."""
        self.worker_thread.requestInterruption()

    def _succeeded(self, addon):
        """Callback for successful removal"""
        self.dialog_timer.stop()
        if self.progress_dialog:
            self.progress_dialog.hide()
        MessageDialog.show_modal(
            MessageDialog.DialogType.INFO,
            "AddonManager_UninstallCompleteDialog",
            translate("AddonsInstaller", "Uninstall complete"),
            translate("AddonInstaller", "Finished removing {}").format(addon.display_name),
            QtWidgets.QMessageBox.Ok,
        )
        self._finalize()

    def _failed(self, addon, message):
        """Callback for failed or partially failed removal"""
        self.dialog_timer.stop()
        if self.progress_dialog:
            self.progress_dialog.hide()
        MessageDialog.show_modal(
            MessageDialog.DialogType.ERROR,
            "AddonManager_UninstallFailedDialog",
            translate("AddonsInstaller", "Uninstall failed"),
            translate("AddonInstaller", "Failed to remove some files") + ":\n" + message,
            QtWidgets.QMessageBox.Ok,
        )
        self._finalize()

    def _finalize(self):
        """Clean up and emit the finished signal"""
        if self.worker_thread.isRunning():
            self.worker_thread.requestInterruption()
            self.worker_thread.quit()
            self.worker_thread.wait(500)
        self.finished.emit()
