#!/usr/bin/env python3
#
# Copyright (c) 2024 Stormux
# Copyright (c) 2010-2012 The Orca Team
# Copyright (c) 2012 Igalia, S.L.
# Copyright (c) 2005-2010 Sun Microsystems Inc.
#
# This library 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 library 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 library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.
#
# Fork of Orca Screen Reader (GNOME)
# Original source: https://gitlab.gnome.org/GNOME/orca

"""Script for sleep mode where Cthulhu ignores events and commands."""

__id__        = "$Id$"
__version__   = "$Revision$"
__date__      = "$Date$"
__copyright__ = "Copyright (c) 2024 Stormux"
__license__   = "LGPL"

import cthulhu.debug as debug
import cthulhu.scripts.default as default
import cthulhu.input_event as input_event
import cthulhu.keybindings as keybindings
import cthulhu.messages as messages
from cthulhu.ax_object import AXObject
from cthulhu.ax_utilities import AXUtilities

class Script(default.Script):
    """The sleep-mode script."""

    def __init__(self, app):
        super().__init__(app)
        self.presentIfInactive = True

    def activate(self):
        """Called when this script is activated."""
        tokens = ["SLEEP MODE: Activating script for", self.app]
        debug.printTokens(debug.LEVEL_INFO, tokens, True)
        
        # Only keep the sleep mode toggle binding active
        self.removeKeyGrabs()
        self.addKeyGrabs()

        # Present sleep mode status
        self.clearBraille()
        self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app))

    def deactivate(self):
        """Called when this script is deactivated."""
        tokens = ["SLEEP MODE: De-activating script for", self.app]
        debug.printTokens(debug.LEVEL_INFO, tokens, True)
        self.removeKeyGrabs()

    def getKeyBindings(self):
        """Only provide the key binding needed to exit sleep mode."""
        keyBindings = keybindings.KeyBindings()
        
        keyBindings.load([("q", keybindings.defaultModifierMask, 
                          keybindings.CTHULHU_CTRL_ALT_MODIFIER_MASK | keybindings.SHIFT_ALT_MODIFIER_MASK,
                          "toggleSleepModeHandler")],
                        self.inputEventHandlers)
        return keyBindings

    def setupInputEventHandlers(self):
        """Sets up the input event handlers for sleep mode."""
        super().setupInputEventHandlers()
        self.inputEventHandlers["toggleSleepModeHandler"] = \
            input_event.InputEventHandler(
                Script.toggleSleepMode,
                "Toggles sleep mode on/off")

    def toggleSleepMode(self, input_event=None):
        """Toggles between sleep mode and regular mode."""
        script_manager = _scriptManager
        script_manager.setActiveScript(script_manager.getDefaultScript(), "Sleep mode toggled")
        self.presentMessage(messages.SLEEP_MODE_DISABLED_FOR % AXObject.get_name(self.app))
        return True

    def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus):
        """Handles changes of focus of interest to the script."""
        tokens = ["SLEEP MODE: focus changed from", oldLocusOfFocus, "to", newLocusOfFocus]
        debug.printTokens(debug.LEVEL_INFO, tokens, True)
        if oldLocusOfFocus is None and AXUtilities.is_application(AXObject.get_parent(newLocusOfFocus)):
            self.clearBraille()
            self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app))
            return

        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def presentKeyboardEvent(self, event):
        """Prevents keyboard echo in sleep mode."""
        msg = "SLEEP MODE: Not presenting keyboard event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)
        return True

    def updateBraille(self, obj, **args):
        """Don't update braille in sleep mode."""
        msg = "SLEEP MODE: Not updating braille."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    # Event handler overrides - all do nothing
    def onActiveChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onActiveDescendantChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onBusyChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onCaretMoved(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onCheckedChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onChildrenAdded(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onChildrenRemoved(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onColumnReordered(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onDocumentLoadComplete(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onDocumentLoadStopped(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onDocumentReload(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onExpandedChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onFocus(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onFocusedChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onMouseButton(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onNameChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onSelectedChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onSelectionChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onShowingChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onTextAttributesChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onTextDeleted(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onTextInserted(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onTextSelectionChanged(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)

    def onWindowActivated(self, event):
        """Callback for window:activate accessibility events."""
        self.clearBraille()
        self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app))

    def onWindowDeactivated(self, event):
        msg = "SLEEP MODE: Ignoring event."
        debug.printMessage(debug.LEVEL_INFO, msg, True)
