#!/usr/bin/env python3

import subprocess
from datetime import datetime
from pathlib import Path

import gi

gi.require_version("Gtk", "3.0")
gi.require_version("GtkLayerShell", "0.1")

from gi.repository import Gtk, Gdk, GdkPixbuf, GLib, GtkLayerShell


CONFIG_FILE = Path("/etc/ekklesia-classroom/device.conf")
CSS_FILE = Path("/etc/ekklesia-classroom/dock/style.css")
ICON_DIR = Path("/etc/ekklesia-classroom/icons")


def read_device_config():
    config = {}

    if not CONFIG_FILE.exists():
        return config

    for raw_line in CONFIG_FILE.read_text().splitlines():
        line = raw_line.strip()

        if not line or line.startswith("#") or "=" not in line:
            continue

        key, value = line.split("=", 1)
        config[key.strip()] = value.strip()

    return config


def enabled(config, key, default=False):
    if key not in config:
        return default

    return config[key].lower() in {
        "1",
        "true",
        "yes",
        "on",
        "enabled",
    }


def launch(command):
    subprocess.Popen(command, start_new_session=True)


def notify(title, message):
    launch([
        "notify-send",
        "--app-name=Ekklesia Classroom",
        title,
        message,
    ])


def themed_icon(*names):
    theme = Gtk.IconTheme.get_default()

    for name in names:
        if theme.has_icon(name):
            return Gtk.Image.new_from_icon_name(
                name,
                Gtk.IconSize.DIALOG,
            )

    return Gtk.Image.new_from_icon_name(
        "application-x-executable",
        Gtk.IconSize.DIALOG,
    )


def custom_icon(filename, size):
    path = ICON_DIR / filename

    if not path.exists():
        return None

    pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
        str(path),
        size,
        size,
        True,
    )

    return Gtk.Image.new_from_pixbuf(pixbuf)


class ClassroomShell(Gtk.Window):
    def __init__(self):
        super().__init__()

        screen = self.get_screen()
        visual = screen.get_rgba_visual()

        if visual is not None:
            self.set_visual(visual)

        self.set_app_paintable(True)
        self.set_name("classroom-shell")
        self.set_decorated(False)
        self.set_resizable(False)

        self.config = read_device_config()

        GtkLayerShell.init_for_window(self)
        GtkLayerShell.set_layer(
            self,
            GtkLayerShell.Layer.TOP,
        )

        GtkLayerShell.set_anchor(
            self,
            GtkLayerShell.Edge.BOTTOM,
            True,
        )
        GtkLayerShell.set_anchor(
            self,
            GtkLayerShell.Edge.LEFT,
            True,
        )
        GtkLayerShell.set_anchor(
            self,
            GtkLayerShell.Edge.RIGHT,
            True,
        )

        GtkLayerShell.set_exclusive_zone(self, 76)
        GtkLayerShell.set_keyboard_interactivity(
            self,
            False,
        )

        layout = Gtk.Overlay()
        layout.set_size_request(-1, 76)

        dock = self.build_dock()

        dock_align = Gtk.Alignment(
            xalign=0.5,
            yalign=0.5,
            xscale=0,
            yscale=0,
        )
        dock_align.add(dock)
        layout.add(dock_align)

        self.clock = Gtk.Label()
        self.clock.get_style_context().add_class("clock")

        clock_align = Gtk.Alignment(
            xalign=1.0,
            yalign=0.5,
            xscale=0,
            yscale=0,
        )
        clock_align.set_padding(
            0,
            0,
            0,
            20,
        )
        clock_align.add(self.clock)

        layout.add_overlay(clock_align)
        layout.set_overlay_pass_through(clock_align, True)

        self.add(layout)

        self.update_time()
        GLib.timeout_add_seconds(
            15,
            self.update_time,
        )

    def build_dock(self):
        dock = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            spacing=10,
        )
        dock.get_style_context().add_class("dock")

        dock.pack_start(
            self.make_button(
                self.browser_icon(),
                lambda *_: launch(
                    ["/usr/local/bin/classroom-browser"]
                ),
            ),
            False,
            False,
            0,
        )

        if enabled(
            self.config,
            "DVD_ENABLED",
            False,
        ):
            dock.pack_start(
                self.make_button(
                    self.dvd_icon(),
                    lambda *_: notify(
                        "DVD",
                        "DVD support is being prepared.",
                    ),
                ),
                False,
                False,
                0,
            )

        dock.pack_start(
            self.make_button(
                self.sanctuary_icon(),
                lambda *_: notify(
                    "Sanctuary",
                    "Sanctuary live view is being prepared.",
                ),
            ),
            False,
            False,
            0,
        )

        return dock

    def make_button(self, image, callback):
        button = Gtk.Button()
        button.set_relief(Gtk.ReliefStyle.NONE)
        button.get_style_context().add_class(
            "dock-button"
        )

        button.add(image)
        button.connect("clicked", callback)

        return button

    def browser_icon(self):
        image = custom_icon(
            "browser.svg",
            28,
        )

        if image is not None:
            return image

        image = themed_icon(
            "web-browser-symbolic",
            "internet-web-browser-symbolic",
        )
        image.set_pixel_size(28)

        return image

    def dvd_icon(self):
        image = custom_icon(
            "dvd.svg",
            40,
        )

        if image is not None:
            return image

        image = themed_icon(
            "media-optical-symbolic",
            "media-optical",
        )
        image.set_pixel_size(28)

        return image

    def sanctuary_icon(self):
        is_live = enabled(
            self.config,
            "SANCTUARY_LIVE",
            False,
        )

        filename = (
            "live.svg"
            if is_live
            else "live-off.svg"
        )

        image = custom_icon(
            filename,
            38,
        )

        if image is not None:
            return image

        image = themed_icon(
            "video-display-symbolic",
            "video-display",
        )
        image.set_pixel_size(28)

        return image

    def update_time(self):
        self.clock.set_text(
            datetime.now().strftime("%-I:%M %p")
        )
        return True


def load_css():
    provider = Gtk.CssProvider()
    provider.load_from_path(
        str(CSS_FILE)
    )

    screen = Gdk.Screen.get_default()

    Gtk.StyleContext.add_provider_for_screen(
        screen,
        provider,
        Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
    )


def main():
    load_css()

    shell = ClassroomShell()
    shell.connect(
        "destroy",
        Gtk.main_quit,
    )
    shell.show_all()

    Gtk.main()


if __name__ == "__main__":
    main()
