import logging

from parallels.common.workflow.base_workflow import BaseWorkflow
from parallels.common.actions.utils.logging_properties \
	import LoggingProperties
from parallels.common.actions.base.legacy_action \
	import LegacyAction
from parallels.common.actions.base.compound_action \
	import CompoundAction
from parallels.common.actions.base.entry_point_action \
	import EntryPointAction
from parallels.common.actions.hosting_settings.convert.dns \
	import DNS as ActionHostingSettingsConvertDNS
from parallels.plesks_migrator.actions.content.web.check_target_web_hosting \
	import CheckTargetWebHosting
from parallels.common.actions.backup.create_converted \
	import CreateConverted
from parallels.common.actions.backup.save_converted \
	import SaveConverted
from parallels.common.actions.backup.remove_content \
	import RemoveContent
from parallels.common.actions.hosting_settings.convert.remap_databases \
	import RemapDatabases
from parallels.common.actions.hosting_settings.convert.remove_subscription_to_plan_relation \
	import RemoveSubscriptionToPlanRelation
from parallels.common.actions.hosting_settings.convert.remove_subscription_default_db_server \
	import RemoveSubscriptionDefaultDBServer
from parallels.common.actions.hosting_settings.convert.remove_subscription_limits_and_permissions \
	import RemoveSubscriptionLimitsAndPermissions
from parallels.common.actions.hosting_settings.convert.remove_maillists \
	import RemoveMaillists
from parallels.common.actions.hosting_settings.convert.remove_domain_keys \
	import RemoveDomainKeys
from parallels.common.actions.hosting_settings.convert.change_webmail_to_horde \
	import ChangeWebmailToHorde
from parallels.common.actions.hosting_settings.convert.remove_disabled_mailsystem_without_resource \
	import RemoveDisabledMailsystemWithoutResource
from parallels.common.actions.hosting_settings.convert.change_catch_all_redirect \
	import ChangeCatchAllRedirect
from parallels.common.actions.hosting_settings.convert.change_subscription_ips \
	import ChangeSubscriptionIPs
from parallels.common.actions.hosting_settings.convert.remove_subscription_external_id \
	import RemoveSubscriptionExternalId
from parallels.common.actions.hosting_settings.convert.change_sysuser_password \
	import ChangeSysuserPassword
from parallels.common.actions.hosting_settings.convert.change_smartermail_password \
	import ChangeSmartermailPassword
from parallels.common.actions.hosting_settings.convert.remove_smartermail_unsupported_features \
	import RemoveSmartermailUnsupportedFeatures
from parallels.common.actions.hosting_settings.convert.change_sysuser_login \
	import ChangeSysuserLogin
from parallels.common.actions.hosting_settings.restore_sysuser_logins \
	import RestoreSysuserLogins
from parallels.common.actions.hosting_settings.check.catch_all_redirect \
	import CatchAllRedirect
from parallels.common.actions.hosting_settings.check.email_empty_password \
	import EmailEmptyPassword
from parallels.common.actions.hosting_settings.check.maillists \
	import Maillists
from parallels.common.actions.dns.forwarding.set_dns_forwarding_not_supported \
	import SetDNSForwardingNotSupported
from parallels.common.actions.dns.forwarding.undo_dns_forwarding_not_supported \
	import UndoDNSForwardingNotSupported
from parallels.common.actions.dns.timings.set_dns_timings_not_supported \
	import SetDNSTimingsNotSupported
from parallels.common.utils.backup_adapter import SubscriptionBackup
from parallels.common.utils.backup_adapter import SubscriptionBackupRaw

logger = logging.getLogger(__name__)

class SharedHostingWorkflow(BaseWorkflow):
	"""Common workflow for shared hosting migration"""

	def __init__(self):
		super(SharedHostingWorkflow, self).__init__()

		self.add_shared_action('fetch-source', CompoundAction(
			description='Fetch information from source panel'
		))

		self.add_entry_point('transfer-accounts', EntryPointAction())

		self.get_path('transfer-accounts').insert_action('check-updates',
			LegacyAction(
			description='Check migrator updates',
			function=lambda ctx: ctx.migrator._check_updates()
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'check-connections', LegacyAction(
				description='Check connections',
				function=lambda ctx: ctx.migrator._check_connections(ctx.options)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'check-target-licenses', LegacyAction(
				description='Check licenses on target servers',
				function=lambda ctx: ctx.migrator._check_target_licenses(ctx.options)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'fetch-source', self.get_shared_action('fetch-source')
		)
		self.get_path('transfer-accounts').insert_action('fetch-target', LegacyAction(
			description='Fetch information from target servers',
			function=lambda ctx: ctx.migrator._fetch(ctx.options, ctx.options.reload_source_data)
		))
		self.get_path('transfer-accounts').insert_action('import-resellers-and-plans', LegacyAction(
			description='Import resellers and plans',
			function=lambda ctx: ctx.migrator._import_resellers_and_plans(ctx.options)
		))
		self.get_path('transfer-accounts').insert_action('convert', LegacyAction(
			description='Convert clients and subscriptions',
			function=lambda ctx: ctx.migrator.convert(ctx.options)
		))
		self.get_path('transfer-accounts').insert_action('check-main-node-disk-space-requirements', LegacyAction(
			description='Check disk space requirements for main target server',
			function=lambda ctx: ctx.migrator.check_main_node_disk_space_requirements(ctx.options)
		))
		self.get_path('transfer-accounts').insert_action('set-apache-restart-interval', LegacyAction(
			description='Set Apache restart interval',
			function=lambda ctx: ctx.migrator._set_apache_restart_interval()
		))
		self.get_path('transfer-accounts').insert_action('restore', LegacyAction(
			description='Import clients and subscriptions',
			function=lambda ctx: ctx.migrator._restore_impl(ctx.options, finalize=False)
		))
		self.get_path('transfer-accounts').insert_action(
			'check-infrastructure', LegacyAction(
				description='Check infrastructure (connections and disk space)',
				function=lambda ctx: ctx.migrator.check_infrastructure(ctx.options)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'restore-hosting', CompoundAction()
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'convert-hosting', CompoundAction(
				description='Convert hosting settings to target panel format'
			)
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'restore-sysuser-logins', CompoundAction(
				description='Restore logins of system users'
			)
		)
		self.get_path('transfer-accounts/restore-hosting/restore-sysuser-logins').insert_action(
			'change-sysuser-logins', RestoreSysuserLogins()
		)
		self.get_path('transfer-accounts/restore-hosting/restore-sysuser-logins').insert_action(
			'change-backup', ChangeSysuserLogin(SubscriptionBackup())
		)
		self.get_path('transfer-accounts/restore-hosting/restore-sysuser-logins').insert_action(
			'save-backup', SaveConverted(SubscriptionBackup()),
		)

		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'windows-refresh-components', LegacyAction(
				description='Refresh components list on target Windows servers',
				function=lambda ctx: ctx.migrator._refresh_service_node_components_for_windows()
			)
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'restore-hosting', LegacyAction(
				description='Restore hosting settings',
				function=lambda ctx: ctx.migrator._restore_hosting(
					ctx.options, None, finalize=False
				)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'restore-status', LegacyAction(
				description='Restore status of suspended clients and subscriptions',
				function=lambda ctx: ctx.migrator.restore_status(
					ctx.options, finalize=False
				)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'restore-apache-restart-interval', LegacyAction(
				description='Restore Apache restart interval',
				function=lambda ctx: ctx.migrator._restore_apache_restart_interval()
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'verify-hosting', LegacyAction(
				description='Verify hosting settings on target',
				function=lambda ctx: ctx.migrator.verify_hosting(
					ctx.options, finalize=False
				)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'copy-content', CompoundAction(
				description='Copy content'
			)
		)
		self.get_path('transfer-accounts/copy-content').insert_action(
			'web', CompoundAction(
				description='Copy web files'
			)
		)
		self.get_path('transfer-accounts/copy-content/web').insert_action(
			'check-target-web-hosting', CheckTargetWebHosting()
		)
		self.get_path('transfer-accounts/copy-content').insert_action(
			'mail', LegacyAction(
				description='Copy mail messages',
				function=lambda ctx: ctx.migrator._copy_mail_content(
					options=ctx.options, finalize=False
				)
			)
		)
		self.get_path('transfer-accounts/copy-content').insert_action(
			'database', LegacyAction(
				description='Copy databases',
				function=lambda ctx: ctx.migrator._copy_db_content(
					ctx.options, finalize=False
				)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'sync-subscription-plan', LegacyAction(
				description='Synchronize subscriptions with plans',
				function=lambda ctx: ctx.migrator._sync_subscription_plan()
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'finalize', LegacyAction(
				description='Count migration statistics, print report',
				function=lambda ctx: ctx.migrator._finalize(True, ctx.options),
				logging_properties=LoggingProperties(info_log=False)
			)
		)

		self.get_path('transfer-accounts').register_shutdown(
			'set-apache-restart-interval',
			'restore-apache-restart-interval'
		)

		convert_hosting = self.get_path(
			'transfer-accounts/restore-hosting/convert-hosting'
		)
		convert_hosting.insert_actions([
			('create-converted-backup', CreateConverted(SubscriptionBackup())),
			('convert-dns', ActionHostingSettingsConvertDNS()),
			('remap-databases', RemapDatabases(SubscriptionBackup())),
			('remove-subscription-to-plan-relation', RemoveSubscriptionToPlanRelation(SubscriptionBackup())),
			('remove-subscription-default-db-server', RemoveSubscriptionDefaultDBServer(SubscriptionBackup())),
			('remove-subscription-limits-and-permissions', RemoveSubscriptionLimitsAndPermissions(SubscriptionBackup())),
			('remove-maillists', RemoveMaillists(SubscriptionBackup())),
			('remove-domain-keys', RemoveDomainKeys(SubscriptionBackup())),
			('change-webmail-to-horde', ChangeWebmailToHorde(SubscriptionBackup())),
			('remove-disabled-mailsystem-without-resource', RemoveDisabledMailsystemWithoutResource(SubscriptionBackup())),
			('change-catch-all-redirect', ChangeCatchAllRedirect(SubscriptionBackup())),
			('change-subscription-ips', ChangeSubscriptionIPs(SubscriptionBackup())),
			('remove-subscription-external-id', RemoveSubscriptionExternalId(SubscriptionBackup())),
			('change-sysuser-password', ChangeSysuserPassword(SubscriptionBackup())),
			('change-smartermail-password', ChangeSmartermailPassword(SubscriptionBackup())),
			('remove-smartermail-upsupported-features', RemoveSmartermailUnsupportedFeatures(SubscriptionBackup())),
			('backup-remove-content', RemoveContent(SubscriptionBackup())),
			('save-backup', SaveConverted(SubscriptionBackup())),
			('check-catch-all-redirect', CatchAllRedirect(SubscriptionBackup())),
			('check-email-empty-password', EmailEmptyPassword(SubscriptionBackup())),
			('check-maillists', Maillists(SubscriptionBackup())),
		])

		self.add_entry_point('check', EntryPointAction())

		self.get_path('check').insert_action(
			'check-updates', LegacyAction(
				description='Check migrator updates',
				function=lambda ctx: ctx.migrator._check_updates()
			)
		)
		self.get_path('check').insert_action('check-connections', LegacyAction(
			description='Check connections',
			function=lambda ctx: ctx.migrator._check_connections(ctx.options)
		))
		self.get_path('check').insert_action('check-target-licenses', LegacyAction(
			description='Check licenses on target servers',
			function=lambda ctx: ctx.migrator._check_target_licenses(ctx.options)
		))
		self.get_path('check').insert_action(
			'fetch-source', self.get_shared_action('fetch-source')
		)
		self.get_path('check').insert_action('fetch-target', LegacyAction(
			description='Fetch information from target servers',
			function=lambda ctx: ctx.migrator._fetch(ctx.options, ctx.options.reload_source_data)
		))

		self.get_path('check').insert_action('check-data', CompoundAction())
		self.get_path('check/check-data').insert_action('check-conflicts', LegacyAction(
			description='Check conflicts for clients, subscriptions, reseller, plans',
			function=lambda ctx: ctx.migrator._convert_model(
				ctx.pre_check_report, ctx.target_existing_objects,
				ctx.options, soft_check=True
			)
		))
		self.get_path('check/check-data').insert_action(
			'check-catch-all-redirect',
			CatchAllRedirect(SubscriptionBackupRaw())
		)
		self.get_path('check/check-data').insert_action(
			'check-email-empty-password',
			EmailEmptyPassword(SubscriptionBackupRaw())
		)
		self.get_path('check/check-data').insert_action(
			'check-maillists',
			Maillists(SubscriptionBackupRaw())
		)
		self.get_path('check').insert_action(
			'print-report', LegacyAction(
				description='Print pre-migration report',
				function=lambda ctx: ctx.migrator.print_report(
					ctx.pre_check_report, "pre_migration_report_tree",
					show_no_issue_branches=False
				)
			)
		)

		# Set up the DNS forwarding.
		#
		# Classic DNS forwarding just does not work by its design: source Plesk
		# server is authoritative for its zones - according to registrar - and
		# will not forward queries about these zones anywhere.  So the DNS
		# forwarding we do by turning source Plesk into slave mode for the
		# migrated zones.
		#
		# This step is separate from transfer-accounts because the
		# steps are following:
		# - transfer-accounts
		# - disable access to both source and target servers for the migrated
		#   subscriptions MANUALLY
		# - set up DNS forwarding
		self.add_entry_point('set-dns-forwarding', EntryPointAction())
		self.add_entry_point('undo-dns-forwarding', EntryPointAction())

		# By default we don't have DNS forwarding support.
		# Should be overridden in child workflow for panels which support DNS forwarding.
		self.get_path('set-dns-forwarding').insert_action(
			'check-source-not-supported', SetDNSForwardingNotSupported()
		)
		self.get_path('undo-dns-forwarding').insert_action(
			'check-source-not-supported', UndoDNSForwardingNotSupported()
		)

		# Set up low DNS timings
		self.add_entry_point('set-low-dns-timings', EntryPointAction())
		self.get_path('set-low-dns-timings').insert_action(
			'check-source-not-supported', SetDNSTimingsNotSupported()
		)

