import os

from parallels.core.migrator import Migrator as CommonMigrator
from parallels.core.utils.common import cached
from parallels.core.utils.paths.hosting_description_web_files import HostingDescriptionWebFiles
from parallels.plesk.hosting_description.converter_to_dump import (
    HostingDescriptionToPleskDumpConverter, read_hosting_description_file
)
from parallels.plesk.source.custom.migrated_subscription import CustomPanelMigratedSubscription
from parallels.plesk.source.custom.global_context import CustomPanelGlobalMigrationContext
from parallels.plesk.source.custom import connections
from parallels.plesk.source.custom.utils.agent_pool import AgentPool


class Migrator(CommonMigrator):
    def __init__(self, config, options):
        super(Migrator, self).__init__(config, options)
        self.global_context.agent_pool = AgentPool()

    @property
    def web_files(self):
        """Object to list files to be transferred from source to target

        :rtype: parallels.core.utils.paths.web_files.BaseWebFiles
        """
        return HostingDescriptionWebFiles()

    def iter_shallow_dumps(self):
        return self.iter_all_server_raw_dumps()

    def iter_all_server_raw_dumps(self):
        for source_info in self.global_context.get_sources_info():
            yield source_info.id, source_info.load_raw_dump()

    def iter_panel_server_raw_dumps(self):
        return self.iter_all_server_raw_dumps()

    def iter_converted_dumps(self):
        for source_info in self.global_context.get_sources_info():
            dump = self.load_converted_dump(source_info.id)
            yield source_info.id, dump

    def create_plesk_config_dump_from_hosting_description(self):
        config = connections.HostingDescriptionConfig(
            source_id='hosting-description',
            path=self.global_context.options.source_file,
            file_format=self.global_context.options.source_format,
        )
        target_dump_dir, _ = os.path.splitext(self.global_context.options.target_file)
        target_plesk_version = self.global_context.conn.target.plesk_server.get_plesk_version()
        converter = HostingDescriptionToPleskDumpConverter(
            data=read_hosting_description_file(config),
            target_dump_file=self.global_context.options.target_file,
            target_plesk_version=target_plesk_version,
            database_servers=list(self.global_context.conn.iter_database_servers()),
        )
        converter.write_dump()

    def _get_source_servers(self):
        servers = {}
        for hosting_description_config in self.global_context.conn.iter_hosting_description_configs():
            server = self.global_context.conn.get_source_server_by_id(hosting_description_config.source_id)
            if server is not None:
                servers[hosting_description_config.source_id] = server.settings()
        return servers

    def _load_connections_configuration(self, global_context, target_panel_type):
        return connections.MigratorConnections(global_context, self._get_target_panel_by_name(target_panel_type))

    def _create_global_context(self):
        return CustomPanelGlobalMigrationContext()

    def _get_source_web_node(self, subscription_name):
        subscription = self._create_migrated_subscription(subscription_name)
        source_node_id = subscription.model.source
        return self.global_context.conn.get_source_server_by_id(source_node_id)

    def _get_source_db_node(self, source_id):
        return self.global_context.conn.get_source_server_by_id(source_id)

    @cached
    def _create_migrated_subscription(self, name):
        return CustomPanelMigratedSubscription(self, name)

    def _get_rsync(self, source_server, target_server, source_ip=None):
        return self.global_context.rsync_pool.get(
            source_server, target_server,
            # specify "/cygdrive" as virtual hosts root, to be able to copy files
            # specified by absolute paths in hosting description file
            '/cygdrive'
        )

    def _get_subscription_content_ip(self, sub):
        return self.global_context.conn.get_source_server_by_id(sub.source).ip
