#!/usr/bin/python3
# This file is part of Epoptes, http://epoptes.org
# Copyright 2010-2018 the Epoptes team, see AUTHORS.
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Launch the epoptes UI.
"""
import getpass
import grp
import os
import os.path
import subprocess
import sys

import epoptes
from epoptes.common import config
from epoptes.core import logger
from epoptes.daemon import uiconnection
from epoptes.ui import gui
from epoptes.ui.common import gettext as _
from gi.repository import Gtk
from twisted.internet import reactor
from twisted.internet.protocol import ClientCreator


LOG = logger.Logger(__file__)


def connection_failed(failure):
    """Errback for gui <=> daemon connection."""
    msg = _("An error occurred while trying to connect to the epoptes service:")
    msg += ' <i>' + failure.getErrorMessage() + '</i>\n\n'
    LOG.c("Connection with epoptes failed:", failure.getErrorMessage())
    # Permission denied error
    if failure.value.osError == 13:
        msg += _("User %s must be a member of group %s to run epoptes.") % \
              (getpass.getuser(), config.system['SOCKET_GROUP'])
    # No such file error
    elif failure.value.osError == 2:
        msg += _("Make sure the epoptes service is running.")
    dlg = Gtk.MessageDialog(type=Gtk.MessageType.ERROR,
                            buttons=Gtk.ButtonsType.OK)
    dlg.set_markup(msg)
    dlg.set_title(_('Service connection error'))
    dlg.run()
    dlg.destroy()
    # noinspection PyUnresolvedReferences
    reactor.stop()


def need_sg_relaunch():
    """After fresh installation, we need to relaunch with `sg`."""
    # If we've already used sg once, don't retry it.
    if os.getenv('EPOPTES_SG'):
        return False
    if not os.path.isfile('/usr/bin/sg'):
        return False
    socket = config.system['DIR'] + '/epoptes.socket'
    if os.access(socket, os.W_OK):
        return False
    try:
        epoptes_members = grp.getgrnam(config.system['SOCKET_GROUP']).gr_mem
    except KeyError:
        return False
    if getpass.getuser() not in epoptes_members:
        return False
    # At this point it makes sense to try relaunching.
    # The backgrounding is to allow sg and sh to terminate.
    LOG.w('Relaunching epoptes using sg to gain group access')
    subprocess.Popen(['/usr/bin/sg', config.system['SOCKET_GROUP'],
                      'EPOPTES_SG=True {} &'.format(' '.join(sys.argv))])
    return True


def main():
    """Usage: epoptes [--version]."""
    if len(sys.argv) > 1:
        if sys.argv[1] in ('--version', '-version'):
            print("Epoptes %s" % epoptes.__version__)
            sys.exit(0)

    # cd to the epoptes directory, so that all paths are relative
    if not os.path.isfile('epoptes.ui'):
        os.chdir('/usr/share/epoptes')

    if need_sg_relaunch():
        sys.exit(0)

    egui = gui.EpoptesGui()
    # noinspection PyUnresolvedReferences
    dfr = ClientCreator(reactor, uiconnection.Daemon, egui)\
        .connectUNIX(config.system['DIR'] + "/epoptes.socket")
    dfr.addErrback(connection_failed)
    # noinspection PyUnresolvedReferences
    reactor.run()


if __name__ == '__main__':
    main()
