#!/usr/bin/env python3
"""
CUBBY — desktop launcher (Debian).

The same web app that runs inside the Android APK, in a WebKitGTK window.
There is no server and no network: the app is loaded straight off disk from
/usr/share/cubby/app/index.html and the whole thing works offline, exactly as
it does on the tablet.

Full screen by default, because the point of this app is that a three-year-old
cannot wander out of it. Press Ctrl+Shift+Q, or Esc twice within two seconds,
to leave — a deliberately grown-up gesture.
"""
import gi, sys, time

gi.require_version("Gtk", "3.0")
try:
    gi.require_version("WebKit2", "4.1")
    from gi.repository import WebKit2 as WebKit
except ValueError:                       # older/newer distros
    gi.require_version("WebKit2", "4.0")
    from gi.repository import WebKit2 as WebKit
from gi.repository import Gtk, Gdk, Gio, GLib

APP = "/usr/share/cubby/app/index.html"


class Cubby(Gtk.Window):
    def __init__(self):
        super().__init__(title="Cubby")
        self.set_default_size(1280, 800)
        self.set_icon_name("cubby")
        self._last_esc = 0.0

        # No right-click menu, no dev tools, no way to navigate anywhere else:
        # every one of those is a door out of the app for a child.
        settings = WebKit.Settings()
        settings.set_enable_developer_extras(False)
        settings.set_enable_write_console_messages_to_stdout(False)
        settings.set_enable_page_cache(False)
        settings.set_enable_html5_database(False)
        settings.set_media_playback_requires_user_gesture(False)
        settings.set_property("enable-back-forward-navigation-gestures", False)

        self.web = WebKit.WebView.new_with_settings(settings)
        self.web.connect("context-menu", lambda *a: True)          # swallow it
        self.web.connect("decide-policy", self._policy)
        self.add(self.web)

        self.connect("key-press-event", self._keys)
        self.connect("destroy", Gtk.main_quit)

        self.web.load_uri(Gio.File.new_for_path(APP).get_uri())
        self.fullscreen()

    def _policy(self, view, decision, dtype):
        """Never leave the bundled app."""
        try:
            if dtype == WebKit.PolicyDecisionType.NAVIGATION_ACTION:
                uri = decision.get_navigation_action().get_request().get_uri()
                if not uri.startswith("file:///usr/share/cubby/"):
                    decision.ignore()
                    return True
        except Exception:
            pass
        return False

    def _keys(self, _w, ev):
        ctrl = ev.state & Gdk.ModifierType.CONTROL_MASK
        shift = ev.state & Gdk.ModifierType.SHIFT_MASK
        name = Gdk.keyval_name(ev.keyval) or ""
        if ctrl and shift and name.lower() == "q":
            Gtk.main_quit()
            return True
        if name == "Escape":                      # two presses, within 2s
            now = time.monotonic()
            if now - self._last_esc < 2.0:
                Gtk.main_quit()
                return True
            self._last_esc = now
            return True
        if name in ("F11",):
            return True                            # she does not get to unfullscreen
        return False


def main():
    if not Gio.File.new_for_path(APP).query_exists(None):
        sys.exit(f"Cubby is not installed properly: {APP} is missing")
    Cubby().show_all()
    Gtk.main()


if __name__ == "__main__":
    main()
