from collections import defaultdict
from parallels.ppa.utils.xml_rpc.poa.poa_api import Identifiers
from parallels.core.utils.common import group_by, group_by_id, obj

ADMIN_ACCOUNT_ID = Identifiers.OID_ADMIN


def list_service_template_hostings(service_template, selected_rt_ids=None):
	included_hostings = defaultdict(list)
	for rt in service_template.resource_types:
		if selected_rt_ids is not None and rt.rt_id not in selected_rt_ids:
			continue
		hosting_type = _get_rt_hosting_type(rt)
		if hosting_type is not None:
			included_hostings[hosting_type].append(rt.rt_id)
	return included_hostings


def list_webspace_resources(subscription, webspace_rt_ids):
	resources = []
	for rt in subscription.resources:
		if webspace_rt_ids is not None and rt.rt_id not in webspace_rt_ids:
			continue
		hosting_type = _get_rt_hosting_type(rt)
		if hosting_type is not None:
			resources.append(hosting_type)
	return resources


def get_subscription_hostings_available(subscription, service_template):
	"""Return list:
	[(hosting_name, available)]
	where available equals sum(subscription.limit - subscription.usage) for all resource types of given hosting type
	"""
	# build [ (hosting_type, rt_id, avail) ]
	hosting_resources_avail = []
	st_rt_by_id = group_by_id(service_template.resource_types, lambda rt: rt.rt_id)
	for res in subscription.resources:
		rt = st_rt_by_id[res.rt_id]
		if res.limit == -1:
			avail = -1
		elif res.usage < res.limit:
			avail = res.limit - res.usage
		else:
			avail = 0
		hosting_type = _get_rt_hosting_type(rt)
		if hosting_type is not None:
			hosting_resources_avail.append(obj(hosting_type=hosting_type, rt_id=res.rt_id, avail=avail))

	return _convert_hosting_resources_avail_to_hostings_avail(hosting_resources_avail)


def get_service_template_hostings_available(service_template):
	"""Return list:
	[(hosting_name, available)]
	where available equals sum(service_template.limit) for all resource types of given hosting type
	"""
	# build [ (hosting_type, rt_id, avail) ]
	hosting_resources_avail = []
	for rt in service_template.resource_types:
		hosting_type = _get_rt_hosting_type(rt)
		if hosting_type is not None:
			hosting_resources_avail.append(obj(hosting_type=hosting_type, rt_id=rt.rt_id, avail=rt.limit))

	return _convert_hosting_resources_avail_to_hostings_avail(hosting_resources_avail)


def get_service_template_mail_provider(service_template):
	"""
	Return the name of mail provider (Postfix or SmarterMail),
	or None, if no mail is available in service template
	"""
	for rt in service_template.resource_types:
		hosting_type = _get_rt_hosting_type(rt)
		if hosting_type == 'mail':
			return _get_mail_provider(rt)
	return None


def get_service_template_by_owner_and_name(service_templates, owner_id, name):
	for st in service_templates:
		if st.owner_id == owner_id and st.name == name:
			return st
	return None


def _convert_hosting_resources_avail_to_hostings_avail(hosting_resources_avail):
	"""merge records for the same hosting_type and return result
	"""
	resources_avail_by_hosting_type = group_by(hosting_resources_avail, lambda res: res.hosting_type)
	hostings_avail = {}
	for hosting_type, resources in resources_avail_by_hosting_type.iteritems():
		avail = 0
		for resource in resources:
			if resource.avail == -1:
				avail = resource.avail
				break
			else:
				avail += resource.avail
		hostings_avail[hosting_type] = avail
	return hostings_avail


def _get_mail_provider(rt):
	for ap in rt.act_params:
		if ap.name == 'plesk_mail.mail_provider':
			return ap.value
	return None

def _get_rt_hosting_type(rt):
	rc_name_to_hosting = {
		'plesk_integration': 'subscription',
		'pleskweb_hosting': 'apache',
		'pleskwebiis_hosting': 'iis',
		'plesk_mail': 'mail',
	}

	if rt.resclass_name in rc_name_to_hosting:
		return rc_name_to_hosting[rt.resclass_name]
	elif rt.resclass_name == 'plesk_db_hosting':
		for ap in rt.act_params:
			if ap.name == 'plesk_db_hosting.type':
				if ap.value in ['mysql', 'mssql', 'mssql2012', 'postgresql']:
					if ap.value == 'mssql2012':
						return 'mssql'
					else:
						return ap.value
	return None
