import parallels
from parallels.core.logging import get_logger
from parallels.core.content.mail.base import CopyMailBase
from parallels.core.content.mail.mail_migrator_utils import get_mailbox_temp_directory, write_account_description_file
from parallels.core.runners.base import BaseRunner
from parallels.core.utils.common import is_empty
from parallels.core.utils.mail_migrator import get_local_mail_migrator_executable
from parallels.core.utils.migrator_utils import get_package_extras_file_path

logger = get_logger(__name__)


class CopyMailIMAP(CopyMailBase):
    @classmethod
    def copy_mailbox(
        cls, subscription, domain, mailbox, mail_service_ip,
        source_mailname=None, source_domain=None, source_password=None
    ):
        """Copy mail messages of a single mailbox

        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        :type domain: parallels.core.dump.data_model.Domain
        :type mailbox: parallels.core.dump.data_model.Mailbox
        :type mail_service_ip: str | unicode
        :type source_mailname: str | unicode | None
        :type source_domain: str | unicode | None
        :type source_password: str | unicode | None
        :rtype: None
        """
        target_server = subscription.mail_target_server

        mail_migrator = get_local_mail_migrator_executable(target_server.is_windows())

        mailbox_temp_dir = get_mailbox_temp_directory(target_server, domain, mailbox)
        with target_server.runner() as runner:
            runner.mkdir(mailbox_temp_dir)

        source_account_description_file = target_server.join_file_path(mailbox_temp_dir, 'source-mailbox-description')
        write_account_description_file(
            target_server, domain, mailbox, source_account_description_file,
            source_mailname, source_domain, source_password
        )
        target_account_description_file = target_server.join_file_path(mailbox_temp_dir, 'target-mailbox-description')
        write_account_description_file(
            target_server, domain, mailbox, target_account_description_file,
            # Target Plesk stores mail messages in directories converted to lowercase,
            # so if you have domain "Example.COM" and mailbox "TESTMailbox", by default mail messages
            # will be stored at "/var/qmail/mailnames/example.com/testmailbox". So, convert domain
            # name and mailbox name to lowercase for the target server when executing mail migrator for
            # mail directory provider.
            convert_to_lowercase=True
        )

        with target_server.runner() as runner:
            assert isinstance(runner, BaseRunner)
            command, args = cls._create_migrate_command(
                mail_migrator, mail_service_ip, mailbox_temp_dir,
                source_account_description_file, target_account_description_file,
                target_server, subscription.get_source_info()
            )
            runner.execute_command(command, args)

            # remove files with mailbox description, as they contain password of mailbox
            runner.remove_file(source_account_description_file)
            runner.remove_file(target_account_description_file)

    @staticmethod
    def _create_migrate_command(
        mail_migrator, mail_service_ip, mailbox_temp_dir,
        source_account_description_file, target_account_description_file,
        target_server, source_info
    ):
        """
        :type mail_migrator: str | unicode
        :type mail_service_ip: str | unicode
        :type mailbox_temp_dir: str | unicode
        :type source_account_description_file: str | unicode
        :type target_account_description_file: str | unicode
        :type target_server: parallels.core.connections.target_servers.TargetServer
        :rtype: tuple
        """
        ca_bundle = get_package_extras_file_path(parallels.core, "cacert/cacert.pem")
        command_str = (
            '{mail_migrator} migrate '
            '--source-account-description-file={source_account_description_file} '
            '--source-host={source_host} '
            '--target-account-description-file={target_account_description_file} '
            '--source-ca-bundle={ca_bundle} '
            '--source-allow-insecure-connections=true'
        )
        args = dict(
            mail_migrator=mail_migrator,
            source_host=mail_service_ip,
            source_account_description_file=source_account_description_file,
            target_account_description_file=target_account_description_file,
            ca_bundle=ca_bundle
        )
        if source_info.config.mail_settings.target_log_enabled:
            command_str += ' --log-file={log_file}'
            args['log_file'] = target_server.join_file_path(mailbox_temp_dir, 'mail-imap-migration.log')

        if not is_empty(source_info.config.mail_settings.target_additional_options):
            command_str += ' ' + source_info.config.mail_settings.target_additional_options

        return command_str, args
