import logging
import os
from parallels.common import MigrationError

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

logger = logging.getLogger(__name__)


class FetchExpandData(CommonAction):
	def get_description(self):
		return "Fetch data from Expand main server"

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		return "Failed to fetch data from Expand main server"

	def run(self, global_context):
		"""
		:type global_context: parallels.expand_migrator.global_context.ExpandGlobalMigrationContext
		"""
		logger.info(u"Fetch Plesk servers information from Expand database.")

		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(u"Expand data file already exists, skip loading")
			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.expand_migrator.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(
				u"No Expand Plesk servers are found for source Plesk server(s) %s. " % (
					format_list(absent_plesk_server_plesk_ids),
				) +
				u"Please fix migrator configuration (selected source Plesks, " +
				u"IP addresses in their sections should match IP addresses of the same Plesk servers in Expand)"
			)

		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(
				u"No Expand centralized mail servers are found for configuration section(s) %s. " % (
					format_list(absent_cmail_plesk_ids),
				) +
				u"Please fix migrator configuration (selected centralized mail servers, " +
				u"IP addresses in their sections should match IP addresses "
				u"of the same centralized mail servers in Expand)"
			)
