#!/usr/share/ucs-test/runner python3
## desc: |
##  Check the UMC query command with a custom INI file.
## roles-not: [basesystem]
## packages:
##   - univention-management-console-module-appcenter
## tags: [appcenter]
## exposure: safe
## bugs: [44768]

from __future__ import print_function
import os
import sys
from univention.appcenter.app_cache import AppCache
from univention.testing.umc import Client
import appcentertest as app_test
import univention.testing.ucr as ucr_test
import univention.testing.strings as str_test
from univention import config_registry


opened_files = []


def open_file(prefix, suffix):
	path = '%s.%s' % (prefix, suffix)
	opened_files.append(path)
	return open(path, 'w')


def cleanup():
	print('')
	print('Removing temporarily created files...')
	for ipath in opened_files:
		if os.path.exists(ipath):
			os.unlink(ipath)


def get_temp_app_prefix(app_cache):
	return '%s/testapp_%s' % (app_cache.get_cache_dir(), str_test.random_name())


def write_ini_file(app_prefix):
	print('Writing INI file: %s.ini' % os.path.basename(app_prefix))
	with open_file(app_prefix, 'ini') as ini_file:
		ini_file.write('''
[Application]
ID=test_app
Code=00
Name=Test App
Version=11
License=freemium
Description=Test App [EN]

[de]
Description=Test App [DE]
''')


def test_ini_data(umc_data, lang):
	sys.stdout.write('Testing INI file entries for correctness... ')
	sys.stdout.flush()
	expected_data = {
		'id': 'test_app',
		'code': '00',
		'name': 'Test App',
		'version': '11',
		'license': 'freemium',
		'description': 'Test App [%s]' % lang,
	}
	for ikey, ival in expected_data.items():
		expected_val = expected_data[ikey]
		assert umc_data[ikey] == ival, 'Entry %s=%s does not match expected value %s!' % (ikey, ival, expected_val)
	print('SUCCESS')


README_TYPES = (
	'README',
	'README_INSTALL',
	'README_POST_INSTALL',
	'README_UPDATE',
	'README_POST_UPDATE',
	'README_UNINSTALL',
	'README_POST_UNINSTALL',
)


def write_readme_file(app_prefix, readme_filename):
	with open_file(app_prefix, readme_filename) as readme_file:
		readme_file.write('--%s--' % readme_filename)


def write_readme_files(app_prefix):
	print('Writing README files:')
	for readme in README_TYPES:
		for lang in ('EN', 'DE'):
			filename = '%s_%s' % (readme, lang)
			print('  %s' % filename)
			write_readme_file(app_prefix, filename)


def test_readme_files(umc_data, lang):
	sys.stdout.write('Testing README file entries for correctness... ')
	sys.stdout.flush()
	for readme in README_TYPES:
		expected_val = '--%s_%s--' % (readme, lang)
		val = umc_data[readme.lower()]
		assert val == expected_val, 'Entry %s=%s does not match expected value %s!' % (readme, val, expected_val)
	print('SUCCESS')


RATINGS = (
	'VendorSupported',
	'EditorsAward',
	'PopularityAward',
)


def write_ratings(app_prefix, *keys):
	print('Writing new META file')
	with open_file(app_prefix, 'meta') as meta_file:
		meta_file.write('[Application]\n')
		for ikey in keys:
			meta_file.write('%s=1\n' % ikey)


def get_ratings(umc_data):
	ratings = set()
	for irating in umc_data.get('rating', []):
		if irating['value'] == 1:
			ratings.add(irating['name'])
	return ratings


def test_ratings(umc_data, *keys):
	sys.stdout.write('Testing rating %s in meta file for correctness... ' % (keys, ))
	sys.stdout.flush()
	assert set(keys) == get_ratings(umc_data), 'Ratings %s do not match expected value %s!' % (get_ratings(umc_data), set(keys))
	print('SUCCESS')


def get_app_from_umc(lang='en_US'):
	# UMC query
	client = Client.get_test_connection(language=lang)
	client.umc_set({'locale': lang})
	apps = client.umc_command('appcenter/query', print_response=False, print_request_data=False).result

	# pick our test app from the list of all apps
	matches = [iapp for iapp in apps if iapp['id'] == 'test_app']
	assert len(matches) > 0, 'The test app does not occur in the list of queried apps!'
	return matches[0]


def test_all():
	cache = AppCache()
	cache.clear_cache()
	app_prefix = get_temp_app_prefix(cache)
	write_ini_file(app_prefix)
	write_readme_files(app_prefix)

	# test English and German localization
	for lang in ('en_US', 'de_DE'):
		lang_suffix = lang.split('_')[0].upper()
		print('')
		print('Testing language: %s' % lang_suffix)

		# test INI and README file data
		app = get_app_from_umc(lang)
		test_ini_data(app, lang_suffix)
		test_readme_files(app, lang_suffix)

	# test ratings for a few combinations
	for rating in (
		(RATINGS[0], RATINGS[2]),
		(RATINGS[1],),
		(RATINGS[0], RATINGS[1], RATINGS[2]),
	):
		cache.clear_cache()
		write_ratings(app_prefix, *rating)
		app = get_app_from_umc()
		test_ratings(app, *rating)


if __name__ == '__main__':
	with ucr_test.UCSTestConfigRegistry() as ucr:
		# make sure that the app center cache dir is not resynced during the test
		# ... this allows us to add our test app data directly to the cache dir
		config_registry.handler_set(['appcenter/umc/update/always=false'])
		try:
			app_test.restart_umc()
			test_all()
		finally:
			app_test.restart_umc()
			cleanup()
