from parallels.plesk.source.plesk import messages
import posixpath
import logging

from collections import namedtuple

from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.utils import subscription_filter
from parallels.core.utils.plesk_utils import convert_wildcard_domain_path
from parallels.core import MigrationError

logger = logging.getLogger(__name__)

Link = namedtuple('Link', ['source', 'link', 'is_hardlink'])


class FixUnixVhostStructure(SubscriptionAction):
	"""Base class to fix vhost structure for Unix servers"""

	def get_description(self):
		return messages.ACTION_FIX_UNIX_VHOST_STRUCTURE_DESCRIPTION

	def get_failure_message(self, global_context, subscription):
		return messages.ACTION_FIX_UNIX_VHOST_STRUCTURE_FAILURE % subscription.name

	def is_critical(self):
		"""If action is critical or not

		If action is critical and it failed for a subscription, migration tool
		won't run the next operations for the subscription.

		:rtype: bool
		"""
		return False

	def filter_subscription(self, global_context, subscription):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""
		return subscription_filter.unix_with_virtual_hosting(
			subscription
		)

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""

		target_server = subscription.web_target_server

		links = self._get_links(subscription, target_server.vhosts_dir)
		with target_server.runner() as runner_target:
			try:
				for link in links:
					if link.is_hardlink:
						for source_file in runner_target.get_files_list(link.source):
							runner_target.sh(
								'ln -f {source}/{source_file} {link}',
								dict(
									source=link.source,
									source_file=source_file,
									link=link.link
								)
							)
					else:
						runner_target.sh(
							'ln -s -f {source} {link}',
							dict(
								source=link.source,
								link=link.link
							)
						)
			except Exception as e:
				logger.debug(messages.LOG_EXCEPTION, exc_info=e)
				raise MigrationError(
					messages.CAN_NOT_CREATE_LINKS_FOR_SUBSCRIPTION % (subscription.name_idn, str(e))
				)

	def _get_links(self, subscription, vhosts_dir):
		vhost_name = subscription.name_idn

		links = [
			Link(
				posixpath.join(vhosts_dir, 'system', vhost_name, 'logs'),
				posixpath.join(vhosts_dir, vhost_name, 'logs'),
				True
			),
			Link(
				posixpath.join(vhosts_dir, 'system', vhost_name, 'logs'),
				posixpath.join(vhosts_dir, 'system', vhost_name, 'statistics'),
				False
			),
			Link(
				posixpath.join(vhosts_dir, 'system', vhost_name, 'statistics'),
				posixpath.join(vhosts_dir, vhost_name),
				False
			),
			Link(
				posixpath.join(vhosts_dir, 'system', vhost_name, 'conf'),
				posixpath.join(vhosts_dir, vhost_name), False
			),
		]
		
		for site in subscription.converted_dump.iter_sites():
			if site.is_virtual_hosting:
				site_name = convert_wildcard_domain_path(site.name.encode('idna'))
				links.extend([
					Link(
						posixpath.join(vhosts_dir, 'system', site_name, 'logs'),
						posixpath.join(vhosts_dir, vhost_name, 'logs', site_name),
						True
					),
					Link(
						posixpath.join(vhosts_dir, 'system', site_name, 'logs'),
						posixpath.join(vhosts_dir, 'system', site_name, 'statistics'),
						False
					),
				])

		return links
