from collections import defaultdict

from parallels.utils import if_not_none, group_by, group_by_id
from parallels.plesks_migrator.migration_list import MigrationList as PlesksMigrationList

class MigrationList(PlesksMigrationList):
	@classmethod
	def _extract_subscriptions(cls, source_data, subscriptions_mapping=None, subscription_filter=None, include_addon_plans=False, target_panel=None):
		processed_subscriptions = set()
		subscriptions = []
	
		plesk_clients_by_id = group_by_id(source_data.expand_objects.plesk_clients, lambda c: c.id)
		expand_clients_by_id = group_by_id(source_data.expand_objects.expand_clients, lambda c: c.id)
		assigned_clients_by_client_id = group_by(source_data.expand_objects.assigned_plesk_clients, lambda c: c.client_id)
		resellers_by_id = group_by_id(source_data.expand_objects.expand_resellers, lambda r: r.id)
		plesk_domains_by_plesk_id = group_by(source_data.expand_objects.plesk_domains, lambda d: d.plesk_id)

		for plesk_id in source_data.plesks:
			for domain in plesk_domains_by_plesk_id[plesk_id]:
				owner_id = assigned_clients_by_client_id[domain.client_id][0].reseller_id if domain.client_id in assigned_clients_by_client_id else None
				owner_login = if_not_none(owner_id, lambda owner_id: resellers_by_id[owner_id].login)
				plesk_client = plesk_clients_by_id[domain.client_id]
				if plesk_client.expand_client_id is None:
					if plesk_client.login != 'admin':
						client_login = plesk_client.login
					else:
						if owner_login is None:	# subscription belongs to Plesk admin, and not assigned to an Expand reseller -> move under ppa-admin
							client_login = 'ppa-admin'
						else:			# subscription belongs to Plesk admin, and assigned to an Expand reseller 'reseller' -> move under ppa-reseller
							client_login = 'ppa-%s' % owner_login
				else:
					client_login = expand_clients_by_id[plesk_client.expand_client_id].info['login']

				if domain.name not in processed_subscriptions:
					subscriptions.append(cls.SubscriptionSourceInfo(
						name=domain.name, plan=domain.tmpl_name, addon_plans=[], 
						reseller=owner_login, customer=client_login
					))
					processed_subscriptions.add(domain.name)

		return subscriptions

	@classmethod
	def _get_plans(cls, source_data, ppa_service_templates, addon_plans=False):
		"""Return the following structure:
		plans[reseller_login][plan_name] = bool: whether this plan exists in PPA
		  reseller_login is either a reseller login or None if owner is admin
		"""
		plans = defaultdict(lambda: defaultdict(bool))
		subscriptions = cls._extract_subscriptions(source_data)
		for subscription in subscriptions:
			plans[subscription.reseller][subscription.plan] = False

		expand_resellers_by_id = group_by_id(source_data.expand_objects.expand_resellers, lambda r: r.id)
		for p in source_data.expand_objects.expand_plans:
			reseller_login = expand_resellers_by_id[p.reseller_id].login if p.reseller_id in expand_resellers_by_id else None
			plans[reseller_login][p.name] = False

		for reseller_login, template_names in ppa_service_templates.iteritems():
			for template_name in template_names:
				plans[reseller_login][template_name] = True

		return plans
	
	@classmethod
	def _get_reseller_contacts(cls, source_data):
		reseller_contacts = {}
		for reseller in source_data.expand_objects.expand_resellers:
			if not reseller.login in reseller_contacts:
				reseller_contacts[reseller.login] = reseller.name
		return reseller_contacts
	
	@classmethod
	def _get_customer_contacts(cls, source_data):
		customer_contacts = {}
		expand_clients_by_id = group_by_id(source_data.expand_objects.expand_clients, lambda c: c.id)
		for customer in source_data.expand_objects.plesk_clients:
			if customer.expand_client_id is None:
				customer_login = customer.login
				customer_pname = customer.pname
			else:
				customer_login = expand_clients_by_id[customer.expand_client_id].info['login']
				customer_pname = expand_clients_by_id[customer.expand_client_id].personal_info['pname']

			if customer_login not in customer_contacts:
				customer_contacts[customer_login] = customer_pname
		return customer_contacts
	
	@classmethod
	def _get_source_subscriptions(cls, source_data):
		return [ domain.name for domain in source_data.expand_objects.plesk_domains ]
