import logging
import itertools

from parallels.common.actions.base.subscription_backup_action import SubscriptionBackupAction
from parallels.common.actions.utils.logging_properties \
	import LoggingProperties
from parallels.utils.ip import is_ipv4, is_ipv6


logger = logging.getLogger(__name__)

class ChangeSubscriptionIPs(SubscriptionBackupAction):
	"""Change IPs according to subscription's hosting addresses"""

	def get_description(self):
		return "Change IP addresses in backup"

	def get_failure_message(self, global_context, subscription):
		return "Failed to change IPs for subscription '%s'" % (subscription.name)

	def get_logging_properties(self):
		return LoggingProperties(info_log=False)

	def _run_subscription_backup(
		self, global_context, subscription, subscription_backup
	):
		all_target_ips = global_context.import_api.get_all_ips()
		ip_address_to_type = { ip.ip_address: ip.ip_type for ip in all_target_ips }

		# Workaround for Plesk bug 130416:
		# When subscription in PPA has no web IPs (has only mail hosting),
		# pleskrestore still needs an IP to call Plesk CLI utilities, and
		# tries to figure it out from provided backup; it fails, picking
		# one of source server's IPs, with which subscription can't be
		# restored. Here we pick a suitable IP for pleskrestore.
		target_ip = global_context.conn.target.main_node_ip
		if subscription_backup.hosting_type != 'none':
			(v4, v6) = (
				subscription.target_public_web_ipv4, 
				subscription.target_public_web_ipv6
			)
		elif is_ipv4(target_ip):
			(v4, v6) = (target_ip, None)
		elif is_ipv6(target_ip):
			(v4, v6) = (None, target_ip)
		else:
			logger.warning(
				u"Cannot find a target IP for substitution in the"
				u" subscription '%s'" % subscription.name)
			
		subscription_backup.change_web_ips([
			(v4, ip_address_to_type.get(v4, 'shared')), 
			(v6, ip_address_to_type.get(v6, 'shared'))
		])
		logger.debug(u"Subscription '%s' IP is set to %s." % (subscription.name, v4))

		for domain in itertools.chain(
			[subscription_backup], 
			subscription_backup.iter_addon_domains()
		):
			if domain.mailsystem is not None:
				domain.mailsystem.change_ips([
					(subscription.target_public_mail_ipv4, 'shared'), 
					(subscription.target_public_mail_ipv6, 'shared')
				])
