#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention Reports
#  Creates reports from LaTeX templates
#
# Copyright 2007-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 __future__ import print_function

import os.path
import shutil
import sys
import locale
from optparse import OptionParser

import univention.debug as ud
import univention.admin.uldap

from univention.config_registry import ConfigRegistry

from univention.lib.i18n import Translation
translation = Translation('univention-directory-reports')
_ = translation.translate

ucr = ConfigRegistry()
ucr.load()


def dump_modules(cfg, module=None, out=sys.stdout):
	"""Dump reports for specific or all known modules."""
	if module is None:
		modules = cfg._reports.keys()
	else:
		modules = [module]
	for module in modules:
		print('Reports for module: %s' % module, file=out)
		for name in cfg.get_report_names(module):
			print(' - %s' % name, file=out)


def main():
	# important! set locale before importing
	locale.setlocale(locale.LC_ALL, "")
	translation.set_language()
	from univention.directory.reports import Report, ReportError, Config

	cfg = Config()

	parser = OptionParser(usage='usage: %prog -m <module> [options] dn1 dn2 ...')
	parser.add_option(
		'-u', '--user', action='store',
		dest='user', default=None, metavar='USERDN',
		help='User-DN for simple LDAP access')
	parser.add_option(
		'-p', '--password', action='store',
		dest='password', default=None,
		help='Password for simple LDAP access')
	parser.add_option(
		'-H', '--header', action='store',
		dest='header', default=None,
		help='File containing the header for the report')
	parser.add_option(
		'-F', '--footer', action='store',
		dest='footer', default=None,
		help='file containing the footer for the report')
	parser.add_option(
		'-s', '--server', action='store',
		dest='server', default=ucr.get('ldap/server/name', 'localhost'),
		help='LDAP server [%default]')
	parser.add_option(
		'-b', '--base', action='store',
		dest='base', default=ucr.get('ldap/base', ''),
		help='LDAP base [%default]')
	parser.add_option(
		'-m', '--module', action='store',
		dest='module', default=None,
		help='admin module defining the report to generate')
	parser.add_option(
		'-r', '--report', action='store',
		dest='report', default=cfg.default_report_name,
		help='Name of the report to use [%default]')
	parser.add_option(
		'-l', '--list', action='store_true',
		dest='list_reports', default=False,
		help='List names of available reports')
	parser.add_option(
		'-c', '--config', action='store',
		dest='config', default='/etc/univention/directory/reports/config.ini',
		help='location of the configuration file [%default]')
	parser.add_option(
		'-d', '--debug', action='store', type='int',
		dest='debug', default=0,
		help='if given than debugging is activated and set to the specified level')
	parser.add_option(
		'--output-dir', action='store',
		help='location of the output report file')
	parser.add_option(
		'--output-name', action='store',
		help='custom output report file name')

	(options, args) = parser.parse_args()

	ud.init('/var/log/univention/directory-reports.log', ud.FLUSH, ud.FUNCTION)
	ud.set_level(ud.ADMIN, options.debug)

	cfg = Config(options.config)

	if options.list_reports:
		dump_modules(cfg, options.module)
		sys.exit(0)

	if not args:
		parser.print_usage(sys.stderr)
		print(_("Error: no DNs specified on command line"), file=sys.stderr)
		sys.exit(2)

	if options.output_name and options.output_name != os.path.basename(options.output_name):
		parser.print_usage(sys.stderr)
		print(_("Error: invalid output_name not allowed characters ['/'] "), file=sys.stderr)
		sys.exit(2)

	# FIXME: why is start_tls=0 used here?
	if options.user and options.password:
		lo = univention.admin.uldap.access(host=options.server, base=options.base, binddn=options.user, bindpw=options.password, start_tls=0)
	else:
		try:
			if ucr['server/role'] == 'domaincontroller_master':
				lo, po = univention.admin.uldap.getAdminConnection(start_tls=0)
			else:
				lo, po = univention.admin.uldap.getMachineConnection(start_tls=0)
		except IOError:
			print(_("Error: user and/or password not specified"), file=sys.stderr)
			parser.print_help(sys.stderr)
			sys.exit(1)

	report = Report(lo, config=cfg)

	try:
		filename = report.create(options.module, options.report, args)
	except ReportError as exc:
		print(_("Error: The %s report could not be created: %s") % (options.report, exc), file=sys.stderr)
		sys.exit(1)

	if not options.output_dir:
		options.output_dir = cfg.get_output_dir() or '/tmp'
	if not options.output_name:
		options.output_name = os.path.basename(filename)
	if not os.path.exists(options.output_dir):
		os.makedirs(options.output_dir, exist_ok=True)
	output_report = os.path.join(options.output_dir, options.output_name)
	filename = shutil.move(filename, output_report)

	print(_('The %s has been created: %s') % (options.report, filename))


if __name__ == "__main__":
	main()
