import logging
import os

from parallels.common.utils.plesk_utils import get_migrator_root_path
from parallels.common.utils import windows_utils
import parallels.common

logger = logging.getLogger(__name__)

class CopyMailPsaMailBackup(object):
	def __init__(self, get_mail_provider_by_subscription_name, windows_rsync):
		self._get_mail_provider_by_subscription_name = \
			get_mail_provider_by_subscription_name
		self._windows_rsync = windows_rsync

	def copy_mail(self, migrator_server, subscription, issues):
		for domain in subscription.converted_mail_backup.iter_domains():
			if domain.mailsystem is None:
				logger.debug(u"Skip copying mail content for the domain %s which has no mail hosting", domain.name)
				continue

			self._copy_domain_mail(migrator_server, subscription, domain)

	def _copy_domain_mail(self, migrator_server, subscription, domain):
		for mailbox in domain.iter_mailboxes():
			self._copy_mailbox(migrator_server, subscription, domain, mailbox)

	def _copy_mailbox(self, migrator_server, subscription, domain, mailbox):
		self._backup_mailbox_content(
			migrator_server, subscription, domain, mailbox
		)
		self._restore_mailbox_content(
			migrator_server, subscription, domain, mailbox
		)

	def _backup_mailbox_content(
		self, migrator_server, subscription, domain, mailbox
	):
		source_server = subscription.mail_source_server

		backup_tool = source_server.get_session_file_path(
			'PSAMailbackup.exe'
		)
		accounts_file = source_server.get_session_file_path(
			'Accounts.xml'
		)
		dump_file = source_server.get_session_file_path(
			'Dump.zip'
		)
		logpath = source_server.get_session_file_path(
			'MailBackupLogs'
		)

		if self._get_mail_provider_by_subscription_name:
			provider = self._get_mail_provider_by_subscription_name(
				subscription.name
			)
			provider_str = ' --provider %s' % (provider,)
		else:
			provider_str = ''


		with source_server.runner() as runner:
			if not windows_utils.file_exists(runner, backup_tool):
				self._upload_files(
					source_server, self._psa_mail_common_files, 'PSAMailcommon'
				)

				remote_dir = source_server.get_session_file_path("locale/en-US")
				runner.mkdir(remote_dir)					
				self._upload_files(
					source_server, self._psa_locale_files, 'PSAMailcommon'
				)

				self._upload_files(
					source_server, self._psa_mail_backup_files, 'PSAMailbackup'
				)

			runner.remove_file(dump_file)
			runner.remove_file(accounts_file)
			runner.upload_file_content(
				accounts_file, self._generate_accounts_file(domain, mailbox)
			)

			runner.sh(
				ur'{backup_tool} --dump-file="{dump}" '
				ur'--logpath="{logpath}" '
				ur'--account-file="{accounts_file}"' + provider_str,
				dict(
					backup_tool=backup_tool,
					dump=dump_file,
					accounts_file=accounts_file,
					logpath=logpath,
				)
			)

	def _restore_mailbox_content(
		self, migrator_server, subscription, domain, mailbox
	):
		target_server = subscription.mail_target_server
		source_server = subscription.mail_source_server

		restore_tool = target_server.get_session_file_path(
			"PSAMailrestore.exe"
		)
		accounts_file = target_server.get_session_file_path(
			'Accounts.xml'
		)
		dump_file = target_server.get_session_file_path(
			'Dump.zip'
		)
		logpath=target_server.get_session_file_path(
			'MailRestoreLogs'
		)

		with target_server.runner() as runner:
			if not windows_utils.file_exists(runner, restore_tool):
				self._upload_files(
					target_server, self._psa_mail_common_files, 
					'PSAMailcommon'
				)

				remote_dir = target_server.get_session_file_path("locale/en-US")
				runner.mkdir(remote_dir)					
				self._upload_files(
					target_server, self._psa_locale_files, 'PSAMailcommon'
				)

				self._upload_files(
					target_server, self._psa_mail_restore_files, 
					'PSAMailrestore'
				)

			runner.remove_file(dump_file)
			runner.remove_file(accounts_file)
			runner.upload_file_content(
				accounts_file, self._generate_accounts_file(domain, mailbox)
			)

		with self._windows_rsync(
			source_server, target_server, subscription.source_mail_ip
		) as rsync:
			rsync.sync(
				'migrator/Dump.zip', 
				windows_utils.convert_path_to_cygwin(dump_file)
			)

		with target_server.runner() as runner:
			runner.sh(
				ur'{restore_tool} --dump-file="{dump}" '
				ur'--logpath="{logpath}" '
				ur'--account-file="{accounts_file}"',
				dict(
					restore_tool=restore_tool,
					dump=dump_file,
					accounts_file=accounts_file,
					logpath=logpath
				)
			)
					
	def _generate_accounts_file(self, domain, mailbox):
		return u"""
<Accounts>
<Domain Name="{domain_name}" StoredName="{domain_name}">
<Account Name="{mailbox_name}" Pwd="{password}" /> 
</Domain>
</Accounts>""".format(
			domain_name=domain.name, 
			mailbox_name=mailbox.name, 
			password=mailbox.password
		).encode('utf-8')

	
	def _upload_files(self, server, files, local_dir):
		with server.runner() as runner:
			for file_name in files:
				local_path = os.path.join(
					get_migrator_root_path(parallels.common), 
					'extras', local_dir, file_name
				)
				remote_path = server.get_session_file_path(file_name)
				runner.upload_file(local_path, remote_path)

	_psa_mail_common_files = [
		"CommunigateProMailsrvprovider.dll", "ForeignMigratorCoreCommon.dll", "ForeignMigratorCoreInterfaces.dll",
		"ForeignMigratorEngineCore.dll", "hMail3mailsrvprovider.dll", "hMail4mailsrvprovider.dll",
		"hMailmailsrvprovider.dll", "ICSharpCode.SharpZipLib.dll", "IMailmailsrvprovider.dll", "Legacy.dll",
		"libmariadb.dll", "MailEnablemailsrvprovider.dll", "MailMsgMigrMng.dll", "MDaemonmailsrvprovider.dll",
		"Merakmailsrvprovider.dll", "msvcr110.dll", "MySqlClient.dll", "psabackupcommon.dll", "psacommon.dll",
		"psacontentfile.dll", "PsaFactory110.dll", "PsaFactory115.dll", "PsaFactory120.dll", "PsaFactory83.dll",
		"PsaFactory90.dll",	"PsaFactory.dll", "PsaMailBackupRestoreCommon.dll", "SmarterMailmailsrvprovider.dll",
		"TCPmailsrvprovider.dll", "zlib1.dll"

	]

	_psa_locale_files = [
		"locale/en-US/CrossSysAgentSup.xml", "locale/en-US/DbMigrator.xml", "locale/en-US/DNSMigrator.xml",
		"locale/en-US/FtpMigrator.xml", "locale/en-US/MailMigrator.xml", "locale/en-US/migrmng.xml",
		"locale/en-US/PsaMigrMng90.xml", "locale/en-US/WINAgentMng.xml", "locale/en-US/WinAgent.xml"
	]

	_psa_mail_backup_files = [
		"PSAMailbackup.exe", "PSAMailbackup.exe.config"
	]

	_psa_mail_restore_files = [
		"PSAMailrestore.exe", "PSAMailrestore.exe.config"
	]
