import logging

from parallels.common.utils.rsync_pool import RsyncPool
from parallels.common.utils import plesk_utils
from parallels.common.utils.poa_utils import get_host_id_by_ip
from parallels.common.utils import windows_utils
from parallels.move_subscriptions.common import HostingType
from parallels.target_panel_ppa.connections.target_server import PPATargetServer

from . import MultipleSubscriptionOperation

logger = logging.getLogger(__name__)

class CopyWindowsWebContentOperation(MultipleSubscriptionOperation):
	logger = logging.getLogger(__name__)

	def __init__(self, move_context):
		self.move_context = move_context

	def run(self, try_subscription, subscriptions):
		logger.info(u"Copy web content of Windows subscriptions")
		for subscription in subscriptions:
			with try_subscription(subscription.name):
				subscription_info = self.move_context.ppa_data.get_subscription_info(
					subscription.name
				)
				self._copy_windows_web_content_single_subscription(
					subscription, subscription_info
				)

	def _copy_windows_web_content_single_subscription(self, subscription, subscription_info):
		source_ppa_host_id = get_host_id_by_ip(self.move_context.conn.poa_api(), subscription.source_ip)
		target_ppa_host_id = get_host_id_by_ip(self.move_context.conn.poa_api(), subscription.target_ip)

		if subscription_info.hosting_type == HostingType.Virtual:
			source_server = PPATargetServer(
				self.move_context.conn, source_ppa_host_id, 
				subscription.source_ip
			)
			target_server = PPATargetServer(
				self.move_context.conn, target_ppa_host_id, 
				subscription.target_ip
			)
			logger.info(
				u"Copy content of subscription '%s' from %s to %s", 
				subscription.name, source_server.description(), 
				target_server.description()
			)
			with source_server.runner() as runner:
				self._configure_firewall_source(
					runner, source_server.description()
				)
			with target_server.runner() as runner:
				self._configure_firewall_target(
					runner, target_server.description()
				)
			
			with target_server.runner() as runner:
				vhosts_dir_target = plesk_utils.get_windows_vhosts_dir(runner)
			with source_server.runner() as runner:
				vhosts_dir_source = plesk_utils.get_windows_vhosts_dir(runner)

			rsync_pool = RsyncPool(self.move_context.session_dir.get_file_path('rsync_path_'))
			rsync = rsync_pool.get(source_server, target_server, vhosts_dir_source)
			rsync.sync(
				source_path="vhosts/%s" % (subscription.name.encode('idna'),),
				target_path=windows_utils.convert_path_to_cygwin(vhosts_dir_target)
			)

			with source_server.runner() as runner:
				self._unconfigure_firewall_source(
					runner, source_server.description()
				)
			with target_server.runner() as runner:
				self._unconfigure_firewall_target(
					runner, target_server.description()
				)

	def _configure_firewall_source(self, runner, node_description):
		try:
			logger.debug("Set up firewall on source IIS node %s", node_description)
			runner.sh('netsh advfirewall firewall add rule name=PPA_MOVE_SUBSCRIPTIONS_INCOMING protocol=TCP dir=in profile=any localport=873 localip=any action=allow')
		except Exception as e:
			logger.error(u"Failed to set up firewall on the source IIS node %s: %s. This may cause copy content to fail.", node_description, e)
			logger.debug(u"Exception:", exc_info=True)

	def _configure_firewall_target(self, runner, node_description):
		try:
			logger.debug("Set up firewall on target IIS node %s", node_description)
			runner.sh('netsh advfirewall firewall add rule name=PPA_MOVE_SUBSCRIPTIONS_OUTGOING protocol=TCP dir=out profile=any remoteport=873 localip=any action=allow')
		except Exception as e:
			logger.error(u"Failed to set up firewall on the target IIS node %s: %s. This may cause copy content to fail.", node_description, e)
			logger.debug(u"Exception:", exc_info=True)

	def _unconfigure_firewall_source(self, runner, node_description):
		try:
			logger.debug("Remove firewall rules on source IIS node %s", node_description)
			runner.sh('netsh advfirewall firewall delete rule name=PPA_MOVE_SUBSCRIPTIONS_INCOMING')
		except Exception as e:
			logger.error(u"Failed to remove firewall rule on the source IIS node %s: %s", node_description, e)
			logger.debug(u"Exception:", exc_info=True)

	def _unconfigure_firewall_target(self, runner, node_description):
		try:
			logger.debug("Remove firewall rules on target IIS node %s", node_description)
			runner.sh('netsh advfirewall firewall delete rule name=PPA_MOVE_SUBSCRIPTIONS_OUTGOING')
		except Exception as e:
			logger.error(u"Failed to remove firewall rule on the target IIS node %s: %s", node_description, e)
			logger.debug(u"Exception:", exc_info=True)
