#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention Management Console
#  handles UMC requests for a specified UMC module
#
# Copyright 2006-2022 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.

from univention.management.console.log import MODULE, log_init, log_reopen
from univention.management.console.config import MODULE_DEBUG_LEVEL, ucr
# don't import univention.management.console.{modules,protocol} here as the locale is not yet set!

from univention.lib.i18n import Locale, Translation

from daemon.daemon import DaemonContext
from argparse import ArgumentParser

import locale
import os
import os.path
import sys
import signal

import notifier
import notifier.log as nflog

if __name__ == '__main__':
	if os.getuid() != 0:
		sys.stderr.write('%s must be started as root\n' % os.path.basename(sys.argv[0]))
		sys.exit(1)

	parser = ArgumentParser(usage="usage: %(prog)s [options]")
	parser.add_argument('-s', '--socket', action='store', dest='socket', help='defines the socket to bind to')
	parser.add_argument('-l', '--language', action='store', dest='language', default='C', help='defines the language to use')
	parser.add_argument('-m', '--module', action='store', dest='module', help='set the UMC daemon module to load')
	parser.add_argument('-n', '--notifier', action='store', dest='notifier', default='generic', help='defines the notifier implementation to use')

	default_debug = MODULE_DEBUG_LEVEL
	parser.add_argument('-d', '--debug', action='store', type=int, dest='debug', default=default_debug, help='if given then debugging is activated and set to the specified level [default: %(default)s]')
	parser.add_argument('-L', '--log-file', action='store', dest='logfile', default='management-console-module-%(module)s', help='specifies an alternative log file [default: %(default)s.log]')
	parser.add_argument('-f', '--foreground', action='store_true', dest='foreground', default=False, help='do not daemonize the process')

	options = parser.parse_args()

	if not options.foreground:
		daemon = DaemonContext(detach_process=False, prevent_core=False, umask=0o077, files_preserve=[x.stream.fileno() for x in nflog.instance.handlers])
		daemon.signal_map = {
			signal.SIGHUP: lambda signal, frame: log_reopen(),
		}
		daemon.open()

	# MUST be called after initializing the daemon
	if options.notifier.lower() == 'generic':
		notifier.init(notifier.GENERIC)
	elif options.notifier.lower() == 'qt':
		import PyQt4.Qt as qt
		qApp = qt.QCoreApplication(sys.argv)
		notifier.init(notifier.QT)

	# init logging
	debug_fd = log_init(options.logfile % {'module': options.module}, options.debug)

	# no notifier logging
	for handler in nflog.instance.handlers[:]:
		nflog.instance.removeHandler(handler)
	# to activate notifier logging
	# nflog.set_level(nflog.DEBUG)
	# nflog.open()

	try:
		locale_obj = Locale(options.language)
		locale.setlocale(locale.LC_MESSAGES, str(locale_obj))
		translation = Translation('univention-management-console')
		translation.set_language(options.language)
	except Exception:
		MODULE.error('The specified locale %r is not available' % (options.language,))

	# this import must be done after the locale is set!
	import univention.management.console.protocol as umcp

	if not options.socket:
		raise SystemError('socket name is missing')

	# make sure the directory where to place socket files exists
	if not os.path.exists('/var/run/univention-management-console'):
		os.mkdir('/var/run/univention-management-console')

	# get the timeout
	session_timeout = 300
	try:
		session_timeout = int(ucr.get('umc/module/timeout', 300))
	except (TypeError, ValueError):
		MODULE.warn('Failed to read module timeout from UCR variable umc/module/timeout. Using default of 300 seconds')

	try:
		with umcp.ModuleServer(options.socket, options.module, check_acls=False, timeout=session_timeout):
			notifier.loop()
	except (SystemExit, KeyboardInterrupt):
		raise
	except BaseException:
		import traceback
		MODULE.error(traceback.format_exc())
		raise
