# Copyright 2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from __future__ import unicode_literals

import io

from portage import os, _encodings
from portage.const import USER_CONFIG_PATH
from portage.tests import TestCase
from portage.tests.resolver.ResolverPlayground import ResolverPlayground
from portage.dep import ExtendedAtomDict
from portage.util import ensure_dirs

class ProfileDefaultEAPITestCase(TestCase):

	def testProfileDefaultEAPI(self):

		repo_configs = {
			"test_repo": {
				"layout.conf": (
					"profile-formats = profile-default-eapi",
					"profile_eapi_when_unspecified = 5"
				),
			}
		}

		profiles = (
			(
				"",
				{
					"package.mask": ("sys-libs/A:1",),
					"package.use": ("sys-libs/A:1 flag",)
				}
			),
			(
				"default/linux",
				{
					"package.mask": ("sys-libs/B:1",),
					"package.use": ("sys-libs/B:1 flag",),
					"package.keywords": ("sys-libs/B:1 x86",)
				}
			),
			(
				"default/linux/x86",
				{
					"package.mask": ("sys-libs/C:1",),
					"package.use": ("sys-libs/C:1 flag",),
					"package.keywords": ("sys-libs/C:1 x86",),
					"parent": ("..",)
				}
			),
		)

		user_profile = {
			"package.mask": ("sys-libs/D:1",),
			"package.use": ("sys-libs/D:1 flag",),
			"package.keywords": ("sys-libs/D:1 x86",),
		}

		test_cases = (
			(lambda x: x._mask_manager._pmaskdict, {
				"sys-libs/A": ("sys-libs/A:1::test_repo",),
				"sys-libs/B": ("sys-libs/B:1",),
				"sys-libs/C": ("sys-libs/C:1",),
				"sys-libs/D": ("sys-libs/D:1",),
			}),
			(lambda x: x._use_manager._repo_puse_dict, {
				"test_repo": {
					"sys-libs/A": {
						"sys-libs/A:1": ("flag",)
					}
				}
			}),
			(lambda x: x._use_manager._pkgprofileuse, (
				{"sys-libs/B": {"sys-libs/B:1": "flag"}},
				{"sys-libs/C": {"sys-libs/C:1": "flag"}},
				{},
				{"sys-libs/D": {"sys-libs/D:1": "flag"}},
			)),
			(lambda x: x._keywords_manager._pkeywords_list, (
					{"sys-libs/B": {"sys-libs/B:1": ["x86"]}},
					{"sys-libs/C": {"sys-libs/C:1": ["x86"]}},
					{"sys-libs/D": {"sys-libs/D:1": ["x86"]}},
				)
			)
		)

		playground = ResolverPlayground(debug=False,
			repo_configs=repo_configs)
		try:
			repo_dir = (playground.settings.repositories.
				get_location_for_name("test_repo"))
			profile_root = os.path.join(repo_dir, "profiles")
			profile_info = [(os.path.join(profile_root, p), data)
				for p, data in profiles]
			profile_info.append((os.path.join(playground.eroot,
				USER_CONFIG_PATH, "profile"), user_profile))

			for prof_path, data in profile_info:
				ensure_dirs(prof_path)
				for k, v in data.items():
					with io.open(os.path.join(prof_path, k), mode="w",
						encoding=_encodings["repo.content"]) as f:
						for line in v:
							f.write("%s\n" % line)

			# The config must be reloaded in order to account
			# for the above profile customizations.
			playground.reload_config()

			for fn, expected in test_cases:
				result = self._translate_result(fn(playground.settings))
				self.assertEqual(result, expected)

		finally:
			playground.cleanup()


	@staticmethod
	def _translate_result(result):
		if isinstance(result, ExtendedAtomDict):
			result = dict(result.items())
		elif isinstance(result, tuple):
			result = tuple(dict(x.items()) for x in result)
		return result
