"""
Menu applet with system/power options for the Panorama panel.
Copyright 2025, roundabout-host.com <vlad@roundabout-host.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public Licence as published by
the Free Software Foundation, either version 3 of the Licence, 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 Licence for more details.

You should have received a copy of the GNU General Public Licence
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""

import os
from pathlib import Path
import locale
import panorama_panel

import gi
gi.require_version("Gtk", "4.0")

from gi.repository import Gtk, GLib, Gio, GioUnix, Gdk


module_directory = Path(__file__).resolve().parent

locale.bindtextdomain("panorama-session-menu", module_directory / "locale")
_ = lambda x: locale.dgettext("panorama-session-menu", x)


class SessionMenu(panorama_panel.Applet):
    name = _("Session menu")
    description = _("Options for system power and the session")
    icon = Gio.ThemedIcon.new("system-shutdown")

    def __init__(self, orientation=Gtk.Orientation.HORIZONTAL, config=None, **kwargs):
        super().__init__(orientation=orientation, config=config, **kwargs)
        if config is None:
            config = {}

        self.trigger_name = config.get("trigger_name", "system-menu")
        self.icon_name = config.get("icon_name", "system-shutdown-symbolic")

        self.button = Gtk.MenuButton()
        self.button.set_has_frame(False)   # flat look
        self.icon = Gtk.Image.new_from_icon_name(self.icon_name)
        self.icon.set_pixel_size(config.get("icon_size", 24))
        self.button.set_child(self.icon)

        self.menu = Gio.Menu()
        self.popover = Gtk.PopoverMenu.new_from_model_full(self.menu, Gtk.PopoverMenuFlags.NESTED)
        self.popover.set_halign(Gtk.Align.START)
        self.popover.set_has_arrow(False)
        panorama_panel.track_popover(self.popover)
        self.button.set_popover(self.popover)

        self.append(self.button)

        self.context_menu = self.make_context_menu()
        panorama_panel.track_popover(self.context_menu)

        right_click_controller = Gtk.GestureClick()
        right_click_controller.set_button(3)
        right_click_controller.connect("pressed", self.show_context_menu)

        self.add_controller(right_click_controller)

        # Introduce the actions
        action_group = Gio.SimpleActionGroup()
        options_action = Gio.SimpleAction.new("options", None)
        options_action.connect("activate", self.show_options)
        action_group.add_action(options_action)
        action_to_command = {
            "shutdown": "systemctl poweroff",
            "reboot": "systemctl reboot",
            "hibernate": "systemctl hibernate",
            "suspend": "systemctl suspend",
            "logout": "wayland-logout",
            "switch-user": "dm-tool switch-to-greeter",
        }
        if "lock_command" in config:
            action_to_command["lock"] = config["lock_command"]
            self.can_lock = True
        else:
            self.can_lock = False
        for action_name, command in action_to_command.items():
            action = Gio.SimpleAction.new(action_name, None)
            action.connect("activate", lambda *args, command=command: GLib.spawn_command_line_async(command))
            action_group.add_action(action)
        self.insert_action_group("applet", action_group)

        # Power menu
        self.power_menu = Gio.Menu()
        self.power_menu.append(_("_Shut down"), "applet.shutdown")
        self.power_menu.append(_("_Restart"), "applet.reboot")
        self.power_menu.append(_("_Hibernate"), "applet.hibernate")
        self.power_menu.append(_("Sus_pend"), "applet.suspend")

        # Session menu
        self.session_menu = Gio.Menu()
        if self.can_lock:
            self.session_menu.append(_("_Lock screen"), "applet.lock")
        self.session_menu.append(_("Switch _user"), "applet.switch-user")
        self.session_menu.append(_("Log _out"), "applet.logout")

        self.menu.append_section(None, self.session_menu)
        self.menu.append_section(None, self.power_menu)

        self.options_window = None

    def add_trigger_to_app(self):
        if self.trigger_name:
            app: Gtk.Application = self.get_root().get_application()
            action = Gio.SimpleAction.new(self.trigger_name, None)
            action.connect("activate", lambda *args: self.button.popup())
            app.add_action(action)

    def make_context_menu(self):
        menu = Gio.Menu()
        menu.append(_("Menu _options"), "applet.options")
        context_menu = Gtk.PopoverMenu.new_from_model(menu)
        context_menu.set_has_arrow(False)
        context_menu.set_parent(self)
        context_menu.set_halign(Gtk.Align.START)
        context_menu.set_flags(Gtk.PopoverMenuFlags.NESTED)
        return context_menu

    def show_context_menu(self, gesture, n_presses, x, y):
        rect = Gdk.Rectangle()
        rect.x = int(x)
        rect.y = int(y)
        rect.width = 1
        rect.height = 1

        self.context_menu.set_pointing_to(rect)
        self.context_menu.popup()

    def show_options(self, _0=None, _1=None):
        ...

    def shutdown(self, app: Gtk.Application):
        app.remove_action(self.trigger_name)

    def get_config(self):
        return {
            "trigger_name": self.trigger_name,
            "icon_name": self.icon_name,
            "icon_size": self.icon.get_pixel_size(),
        }

    def set_panel_position(self, position):
        self.popover.set_position(panorama_panel.OPPOSITE_POSITION[position])
        self.button.set_direction(panorama_panel.POSITION_TO_ARROW[panorama_panel.OPPOSITE_POSITION[position]])
