# -----------------------------------------------------------------------------
# Copyright (c) 2021- Spyder Project Contributors
#
# Released under the terms of the MIT License
# (see LICENSE.txt in the project root directory for details)
# -----------------------------------------------------------------------------

"""Plugin registry configuration page."""

# Third party imports
from pyuca import Collator
from qtpy.QtWidgets import QVBoxLayout, QLabel

# Local imports
from spyder.api.preferences import PluginConfigPage
from spyder.api.translations import _
from spyder.utils.palette import SpyderPalette
from spyder.widgets.elementstable import ElementsTable
from spyder.widgets.helperwidgets import FinderWidget


class PluginsConfigPage(PluginConfigPage):

    def setup_page(self):
        newcb = self.create_checkbox
        self.plugins_checkboxes = {}

        header_label = QLabel(
            _(
                "Disable a Spyder plugin (external or built-in) to prevent it "
                "from loading until re-enabled here, to simplify the interface "
                "or in case it causes problems."
            )
        )
        header_label.setWordWrap(True)

        # To save the plugin elements
        internal_elements = []
        external_elements = []

        # ------------------ Internal plugins ---------------------------------
        for plugin_name in self.plugin.all_internal_plugins:
            (conf_section_name, PluginClass) = (
                self.plugin.all_internal_plugins[plugin_name]
            )

            if not getattr(PluginClass, "CAN_BE_DISABLED", True):
                # Do not list core plugins that can not be disabled
                continue

            plugin_state = self.get_option(
                "enable", section=conf_section_name, default=True
            )
            cb = newcb(
                "",
                "enable",
                default=True,
                section=conf_section_name,
                restart=True,
            )

            internal_elements.append(
                dict(
                    title=PluginClass.get_name(),
                    description=PluginClass.get_description(),
                    icon=PluginClass.get_icon(),
                    widget=cb,
                    additional_info=_("Built-in"),
                    additional_info_color=SpyderPalette.COLOR_TEXT_4,
                )
            )

            self.plugins_checkboxes[plugin_name] = (cb.checkbox, plugin_state)

        # ------------------ External plugins ---------------------------------
        for plugin_name in self.plugin.all_external_plugins:
            (conf_section_name, PluginClass) = (
                self.plugin.all_external_plugins[plugin_name]
            )

            if not getattr(PluginClass, "CAN_BE_DISABLED", True):
                # Do not list external plugins that can not be disabled
                continue

            plugin_state = self.get_option(
                f"{conf_section_name}/enable",
                section=self.plugin._external_plugins_conf_section,
                default=True,
            )
            cb = newcb(
                "",
                f"{conf_section_name}/enable",
                default=True,
                section=self.plugin._external_plugins_conf_section,
                restart=True,
            )

            external_elements.append(
                dict(
                    title=PluginClass.get_name(),
                    description=PluginClass.get_description(),
                    icon=PluginClass.get_icon(),
                    widget=cb,
                )
            )

            self.plugins_checkboxes[plugin_name] = (cb.checkbox, plugin_state)

        # Sort elements by title for easy searching
        collator = Collator()
        internal_elements.sort(key=lambda e: collator.sort_key(e["title"]))
        external_elements.sort(key=lambda e: collator.sort_key(e["title"]))

        # Build plugins table, showing external plugins first.
        self._plugins_table = ElementsTable(
            self, add_padding_around_widgets=True
        )
        self._plugins_table.setup_elements(
            external_elements + internal_elements
        )

        # Finder to filter plugins
        finder = FinderWidget(
            self,
            find_on_change=True,
            show_close_button=False,
            set_min_width=False,
        )
        finder.sig_find_text.connect(self._do_find)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(header_label)
        layout.addSpacing(15)
        layout.addWidget(self._plugins_table)
        layout.addWidget(finder)
        layout.addSpacing(15)
        self.setLayout(layout)

    def apply_settings(self):
        for plugin_name in self.plugins_checkboxes:
            cb, previous_state = self.plugins_checkboxes[plugin_name]
            if cb.isChecked() and not previous_state:
                self.plugin.set_plugin_enabled(plugin_name)
                PluginClass = None
                external = False
                if plugin_name in self.plugin.all_internal_plugins:
                    (__, PluginClass) = self.plugin.all_internal_plugins[
                        plugin_name
                    ]
                elif plugin_name in self.plugin.all_external_plugins:
                    (__, PluginClass) = self.plugin.all_external_plugins[
                        plugin_name
                    ]
                    external = True  # noqa

                # TODO: Once we can test that all plugins can be restarted
                # without problems during runtime, we can enable the
                # autorestart feature provided by the plugin registry:
                # self.plugin.register_plugin(self.main, PluginClass,
                #                             external=external)
            elif not cb.isChecked() and previous_state:
                # TODO: Once we can test that all plugins can be restarted
                # without problems during runtime, we can enable the
                # autorestart feature provided by the plugin registry:
                # self.plugin.delete_plugin(plugin_name)
                pass
        return set({})

    def _do_find(self, text):
        self._plugins_table.do_find(text)
