#!/usr/bin/env python3
"""BackOne system tray — opens /app UI and addon deep links."""
import os
import signal
import subprocess
import sys
import threading
import urllib.request

import gi
gi.require_version('Gtk', '3.0')
try:
    gi.require_version('AyatanaAppIndicator3', '0.1')
    from gi.repository import AyatanaAppIndicator3 as AppIndicator3
except (ImportError, ValueError):
    gi.require_version('AppIndicator3', '0.1')
    from gi.repository import AppIndicator3

from gi.repository import GLib, Gtk

APP_URL = os.environ.get('BACKONE_APP_URL', 'http://127.0.0.1:9993/app/')
HEALTH_URL = os.environ.get('BACKONE_HEALTH_URL', 'http://127.0.0.1:9993/health')
ICON_NAME = 'network-workgroup'


class BackOneTray:
    def __init__(self):
        self._windows = []
        self.indicator = AppIndicator3.Indicator.new(
            'backone-tray',
            ICON_NAME,
            AppIndicator3.IndicatorCategory.APPLICATION_STATUS,
        )
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
        self.indicator.set_menu(self._build_menu())
        try:
            self.indicator.connect('activate', lambda *_: self._open_url(APP_URL))
        except TypeError:
            pass
        self._update_status()
        GLib.timeout_add_seconds(30, self._on_timer)

    def _build_menu(self):
        menu = Gtk.Menu()

        def add_item(label, callback):
            item = Gtk.MenuItem(label=label)
            item.connect('activate', lambda *_: callback())
            item.show()
            menu.append(item)
            return item

        add_item('Open BackOne App', lambda: self._open_url(APP_URL))
        add_item('Voice', lambda: self._open_url(APP_URL + '#/voice'))
        add_item('Video', lambda: self._open_url(APP_URL + '#/video'))
        add_item('Chat', lambda: self._open_url(APP_URL + '#/chat'))
        menu.append(Gtk.SeparatorMenuItem())
        add_item('Restart BackOne Service', self._restart_service)
        add_item('Quit Tray', Gtk.main_quit)
        menu.show()
        return menu

    def _service_ok(self):
        try:
            with urllib.request.urlopen(HEALTH_URL, timeout=2) as resp:
                return resp.status == 200
        except Exception:
            return False

    def _update_status(self):
        title = 'BackOne (online)' if self._service_ok() else 'BackOne (offline)'
        self.indicator.set_title(title)

    def _on_timer(self):
        self._update_status()
        return True

    def _open_url(self, url):
        if self._try_webkit(url):
            return
        for cmd in (
            ['xdg-open', url],
            ['gio', 'open', url],
            ['sensible-browser', url],
        ):
            try:
                subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                return
            except OSError:
                continue

    def _try_webkit(self, url):
        try:
            gi.require_version('WebKit2', '4.1')
        except ValueError:
            try:
                gi.require_version('WebKit2', '4.0')
            except ValueError:
                return False
        from gi.repository import WebKit2

        win = Gtk.Window(title='BackOne')
        win.set_default_size(900, 640)
        view = WebKit2.WebView()
        view.load_uri(url)
        win.add(view)
        win.connect('destroy', lambda w: self._windows.remove(w) if w in self._windows else None)
        self._windows.append(win)
        win.show_all()
        return True

    def _restart_service(self):
        subprocess.Popen(
            ['pkexec', 'systemctl', 'restart', 'backone'],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
        )


def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    BackOneTray()
    Gtk.main()


if __name__ == '__main__':
    sys.exit(main())
