# window.py
#
# Copyright 2024 Hari Rana (TheEvilSkeleton)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

from gettext import gettext as _
from typing import Any, cast

from gi.repository import Adw, GLib, GObject, Gtk

from refine.logger import logger

# ruff: noqa: F401
from refine.widgets.adjustment import Adjustment
from refine.widgets.base import BaseInterface
from refine.widgets.boolean_switch_row import BooleanSwitchRow
from refine.widgets.combo_row import ComboRow
from refine.widgets.data_combo_row import DataComboRow
from refine.widgets.flags_switch_row import FlagsSwitchRow
from refine.widgets.font_row import FontRow
from refine.widgets.panel_item import PanelItem
from refine.widgets.reset_button import ResetButton
from refine.widgets.value_combo_row import ValueComboRow
from refine.widgets.value_switch_row import ValueSwitchRow
from refine.widgets.window_buttons_row import WindowButtonsRow


@Gtk.Template.from_resource("/page/tesk/Refine/widgets/panel-page.ui")
class PanelPage(Adw.PreferencesPage):
    """Panel page containing options."""

    __gtype_name__ = "PanelPage"


@Gtk.Template.from_resource("/page/tesk/Refine/window.ui")
class Window(Adw.ApplicationWindow):
    """The main window singleton class."""

    __gtype_name__ = "Window"

    stack = Gtk.Template.Child()
    continue_button = Gtk.Template.Child()
    panels_section = Gtk.Template.Child()
    unsupported_status_page = Gtk.Template.Child()
    main_navigation_split_view = Gtk.Template.Child()

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)

        self._verify_environment()

        self.needs_restart: list[Gtk.Widget] = []

        panels_schema = (
            "/page/tesk/Refine/sections/appearance.ui",
            "/page/tesk/Refine/sections/mouse-touchpad.ui",
            "/page/tesk/Refine/sections/power.ui",
            "/page/tesk/Refine/sections/shell-compositor.ui",
            "/page/tesk/Refine/sections/sound.ui",
            "/page/tesk/Refine/sections/wellbeing.ui",
        )

        panels_list = Gtk.StringList.new(panels_schema)

        self.panels_section.bind_model(panels_list, self._create_item_func)

        first_item = self.panels_section.get_item(0)
        self._set_preferences_page(first_item)

    def _create_item_func(
        self, panel: Gtk.StringObject, *_args: Any
    ) -> Adw.SidebarItem:
        builder = Gtk.Builder.new_from_resource(panel.get_string())

        item = PanelItem()
        page = builder.get_object("page")

        item.page = page  # type: ignore [method-assign]

        item.page.bind_property(
            "icon-name", item, "icon-name", GObject.BindingFlags.SYNC_CREATE
        )
        item.page.bind_property(
            "title", item, "title", GObject.BindingFlags.SYNC_CREATE
        )

        return item

    def _set_preferences_page(self, item: PanelItem, *_args: Any) -> None:
        navigation_page = self.main_navigation_split_view.get_content()
        toolbar_view = navigation_page.get_child()

        toolbar_view.set_content(item.page)
        navigation_page.set_title(item.page.get_title())

    @Gtk.Template.Callback()
    def _set_preferences_page_cb(
        self, sidebar: Adw.Sidebar, index: int, *_args: Any
    ) -> None:
        item = sidebar.get_item(index)
        self._set_preferences_page(item)
        self.main_navigation_split_view.set_show_content(True)

    def _verify_environment(self) -> None:
        if GLib.getenv("XDG_CURRENT_DESKTOP") != "GNOME":
            self.stack.set_visible_child_name("unsupported-environment-page")
            self.continue_button.connect(
                "clicked", lambda _: self.stack.set_visible_child_name("refine-page")
            )

            unintended_behavior_label = _(
                "Some settings may not work as intended and could lead to undesirable behavior."
            )
            unintended_behavior_label = f"<b>{unintended_behavior_label}</b>"

            if GLib.getenv("XDG_SESSION_DESKTOP") == "gnome":
                description = (
                    _(
                        "Refine only supports versions of GNOME that have not been modified by the operating system."
                    )
                    + " "
                    + unintended_behavior_label
                )
            else:
                description = (
                    _(
                        "Refine is only intended to run on the GNOME desktop environment."
                    )
                    + " "
                    + unintended_behavior_label
                )

            self.unsupported_status_page.set_description(description)

    # TODO: Find a way to request a logout dialog
    @GObject.Signal
    def restart_items_changed(self, widget: Gtk.Widget) -> None:
        logger.info(f"{self.__class__.__name__}::restart-items-changed signal emitted")

        if not (panel := cast("PanelPage", widget.get_ancestor(PanelPage))):
            return

        try:
            if not (banner := panel.get_banner()):
                return
        except (AttributeError, TypeError):
            return

        try:
            self.needs_restart.remove(widget)
            banner.set_revealed(False)
        except ValueError:
            self.needs_restart.append(widget)
            banner.set_revealed(True)
