from parallels.common.actions.base.common_action import CommonAction
from parallels.common import target_data_model


class ConvertAuxUserRoles(CommonAction):
	def get_description(self):
		return "Convert auxiliary user roles"

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		return "Failed to convert auxiliary user roles"

	def run(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		target_model = global_context.target_model.model
		dump = get_source_dump(global_context)
		for target_client_id, target_client in target_model.clients.items():
			if not target_client_id:
				roles = dump.iter_admin_auxiliary_user_roles() 
			else:
				source_client = dump.get_client(target_client.login)
				roles = source_client.auxiliary_user_roles
			target_client.auxiliary_user_roles.extend(roles)


class ConvertAuxUsers(CommonAction):
	def get_description(self):
		return "Convert auxiliary users"

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		return "Failed to convert auxiliary users"

	def run(self, global_context):
		"""Find and add auxusers to the target model.

		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		target_model = global_context.target_model.model
		dump = get_source_dump(global_context)
		for target_client_id, target_client in target_model.clients.items():
			if not target_client_id:
				auxuser_list = dump.iter_admin_auxiliary_users()
			else:
				source_client = dump.get_client(target_client.login)
				auxuser_list = source_client.auxiliary_users
			for auxuser in auxuser_list:
				self._add_auxuser(auxuser, target_client, global_context)

	def _add_auxuser(self, raw_auxuser, client, context):
		"""Convert aux users, append them to the target model."""
		if raw_auxuser.name == 'admin':
			return
		converted_auxuser = self._convert_auxuser(raw_auxuser)
		password = self._get_auxuser_password(
				raw_auxuser, client.login, context)
		converted_auxuser.password = password
		client.auxiliary_users.append(converted_auxuser)
	
	def _convert_auxuser(self, raw_auxuser):
		"""Create aux user object for target model."""
		personal_info = dict(raw_auxuser.personal_info)
		if 'email' not in personal_info:
			personal_info['email'] = self._get_auxuser_email(raw_auxuser)
		if raw_auxuser.contact is not None:
			auxuser_contact = raw_auxuser.contact
		else:
			auxuser_contact = raw_auxuser.name
		return target_data_model.AuxiliaryUser(
			login=raw_auxuser.name, password=None, name=auxuser_contact,
			roles=set(raw_auxuser.roles), personal_info=personal_info,
			is_active=raw_auxuser.is_active,
			subscription_name=raw_auxuser.subscription_name,
			is_domain_admin=raw_auxuser.is_domain_admin
		)

	def _get_auxuser_email(self, raw_auxuser):
		# 'email' is mandatory parameter (according to importer), but it
		# may be missing in Plesk 8 domain admin or mail accounts
		if raw_auxuser.email:
			return raw_auxuser.email
		elif '@' in raw_auxuser.name:
			return raw_auxuser.name
		else:
			return u"admin@%s" % raw_auxuser.name

	def _get_auxuser_password(self, raw_auxuser, client_login, context):
		if raw_auxuser.password.type == 'plain':
			password = raw_auxuser.password.text
		else:
			password = context.password_holder.get(
					'auxiliary_user', (client_login, raw_auxuser.name))
		return password


def get_source_dump(context):
	""" Return source dump object for a target model client."""
	settings_list = context.migrator.source_plesks
	settings = settings_list.values()
	return context.migrator.load_raw_plesk_backup(settings.pop())
