from parallels.plesk.source.expand import messages
import logging
import os
from parallels.core import MigrationError

from parallels.core.actions.base.common_action import CommonAction
from parallels.core.utils.yaml_utils import write_yaml, read_yaml
from parallels.plesk.source.expand.expand_data.source import ExpandDataSource
from parallels.core.utils.common import format_list

logger = logging.getLogger(__name__)


class FetchExpandData(CommonAction):
	def get_description(self):
		return messages.ACTION_FETCH_DATA_FROM_EXPAND_MAIN_SERVER_DESCRIPTION

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		"""
		return messages.FAILED_TO_FETCH_DATA_FROM_EXPAND

	def run(self, global_context):
		"""
		:type global_context: parallels.plesk.source.expand.global_context.ExpandGlobalMigrationContext
		"""
		logger.info(messages.FETCH_PLESK_SERVERS_INFORMATION_FROM_EXPAND)

		expand_data_model_filename = global_context.session_files.get_path_to_expand_data_model_file()
		if not global_context.options.reload_source_data and os.path.exists(expand_data_model_filename):
			logger.info(messages.SKIP_LOADING_EXPAND_DATA_FILE)
			global_context.expand_data = read_yaml(expand_data_model_filename)
		else:
			data_source = ExpandDataSource(global_context.conn.expand_main_server)
			expand_data_model = data_source.get_model(
				global_context.conn.get_source_plesks(),
				global_context.conn.get_centralized_mail_servers()
			)
			self._check_source_data_complete(global_context, expand_data_model)
			global_context.expand_data = expand_data_model
			write_yaml(expand_data_model_filename, expand_data_model)

	@staticmethod
	def _check_source_data_complete(global_context, expand_objects):
		"""Check that source data (model) is complete.
		At this moment only check that:
		- Expand Plesk servers in model include source Plesk servers selected in migrator configuration.
		- Expand centralized mail servers in model include centralized mail servers selected in migrator configuration.

		:type global_context: parallels.plesk.source.expand.global_context.ExpandGlobalMigrationContext
		"""
		expand_plesk_server_plesk_ids = set([s.plesk_id for s in expand_objects.servers])
		config_plesk_server_plesk_ids = set(global_context.conn.get_source_plesks().keys())
		absent_plesk_server_plesk_ids = config_plesk_server_plesk_ids - expand_plesk_server_plesk_ids
		if len(absent_plesk_server_plesk_ids) > 0:
			raise MigrationError(
				messages.NO_EXPAND_PLESK_SERVERS_FOR_SOURCE_PLESK_SERVER % (
					format_list(absent_plesk_server_plesk_ids),
				) +
				messages.IP_ADDRESSES_DO_NOT_MATCH
			)

		expand_cmail_plesk_ids = set([c.plesk_id for c in expand_objects.centralized_mail_servers])
		config_cmail_plesk_ids = set(global_context.conn.get_centralized_mail_servers().keys())
		absent_cmail_plesk_ids = config_cmail_plesk_ids - expand_cmail_plesk_ids
		if len(absent_cmail_plesk_ids) > 0:
			raise MigrationError(
				messages.NO_EXPAND_CMAIL_SERVERS_FOR_SERVER_DESCRIBED_IN_CONFIG % (
					format_list(absent_cmail_plesk_ids),
				) +
				messages.IP_ADDRESSES_CMAIL_DO_NOT_MATCH
			)
