#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention Updater
#  univention-add-app
#
# Copyright 2012-2014 Univention GmbH
#
# http://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
# <http://www.gnu.org/licenses/>.
#

import sys
from optparse import OptionParser
import subprocess

from univention.lib.package_manager import PackageManager
from univention.config_registry import ConfigRegistry
from univention.updater import UniventionUpdater
try:
	from univention.management.console.modules.appcenter.util import ComponentManager, install_opener
	from univention.management.console.modules.appcenter.app_center import Application, LICENSE
except ImportError:
	sys.stderr.write('univention-management-console-module-appcenter must be installed\n')
	sys.exit(2)

def simple_handler(f):
	def _simple_handler(msg):
		msg = '%s\n\r' % msg.strip()
		f.write(msg)
	return _simple_handler

if __name__ == '__main__':
	usage = '%prog <component> [-a] [-m] [-l] [<package> ...]'
	description = '%prog prepares the corresponding repository settings for the specified component and installs the given packages.'
	parser = OptionParser(usage=usage, description=description)
	parser.add_option("-a", "--all", action="store_true", dest="install_all", default=False,
			help="Installs all DefaultPackages of the app. If DC master or backup, also installs DefaultPackagesMaster. Performs dist-upgrade when upgrading an existing app!")
	parser.add_option("-m", "--master", action="store_true", dest="install_master", default=False,
			help="If DC master or backup, installs DefaultPackagesMaster. Performs dist-upgrade when upgrading an existing app! Has no meaning when used together with --all")
	parser.add_option("-l", "--latest", action="store_true", dest="install_latest", default=False,
			help="<component> is not the component's name but the ID of the application. And always the latest available gets added.")
	options, args = parser.parse_args()
	try:
		component_id = args[0]
	except IndexError:
		parser.print_usage()
		sys.exit(1)

	# for compatibility with 3.1-0. may be removed with 3.2-0
	packages = args[1:]

	ucr = ConfigRegistry()
	ucr.load()
	install_opener(ucr)
	updater = UniventionUpdater(False)
	component_manager = ComponentManager(ucr, updater)
	package_manager = PackageManager(info_handler=simple_handler(sys.stdout), error_handler=simple_handler(sys.stderr), always_noninteractive=True)
	requested_app = None
	function = 'install'
	if options.install_latest:
		requested_app = Application.find(component_id)
		if requested_app and requested_app.candidate:
			function = 'update'
			requested_app = requested_app.candidate
	else:
		for app in Application.all():
			requested_apps = filter(lambda iapp: iapp.component_id == component_id, app.versions)
			if requested_apps:
				requested_app = requested_apps[0]
				for iapp in app.versions:
					if iapp.is_installed(package_manager):
						function = 'update'
				break
	if requested_app is None:
		sys.stderr.write('App "%s" not found\n' % component_id)
		sys.exit(1)
	if not LICENSE.allows_using(requested_app.get('notifyvendor')):
		sys.stderr.write('App "%s" may not be installed\n' % requested_app.name)
		sys.exit(1)
	success = True

	manually = False
	if options.install_all or options.install_master:
		only_master_packages = not options.install_all
		requested_app.versions = Application.find(requested_app.id).versions
		requested_app.candidate = None # delete any possible candidate (newer version)
		if only_master_packages:
			function = '%s-schema' % function
		success = requested_app.install(package_manager, component_manager, add_component=False, send_as=function, only_master_packages=only_master_packages) and success
	else:
		requested_app._send_information(function, 200)
		manually = True

	# for compatibility with 3.1-0. should be removed with 3.2-0
	if packages:
		# some legacy call to install the default packages on the command line
		legacy_call = all(package in packages for package in requested_app.get('defaultpackages'))
		previously_registered = requested_app.register(component_manager, package_manager)
		success = package_manager.install(*packages) and success
		if not success or not legacy_call:
			requested_app.unregister_all_and_register(previously_registered)
		subprocess.call(['/usr/sbin/univention-register-apps'])
	elif manually:
		component_manager.put_app(requested_app)
		package_manager.update()
		sys.stderr.write('WARNING: Using neither --all nor --master is deprecated. Applications may not be registerd properly\n')

	if success:
		sys.exit(0)
	else:
		sys.exit(100) # apt-get error code

