import posixpath
import logging

from collections import namedtuple

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.common.utils import subscription_filter
from parallels.common.utils.plesk_utils import convert_wildcard_domain_path
from parallels.common 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 "Fix vhost structure for Unix servers"

	def get_failure_message(self, global_context, subscription):
		return "Failed to fix vhost structure for subscription '%s'" % (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.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		return subscription_filter.unix_with_virtual_hosting(
			subscription
		)

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.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(u"Exception: ", exc_info=e)
				raise MigrationError(
					u"Can't create links for subscription '%s' with error '%s'." %
					(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_backup.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
