from parallels.core import messages
from collections import namedtuple
import os
import logging
from parallels.core.utils.yaml_utils import pretty_yaml

from parallels.core.utils.common import cached
from parallels.core.dump import save_backup_tar

logger = logging.getLogger(__name__)


class DumpAll(namedtuple('DumpAll', [])):
	def covers(self, selection):
		"""Check if this selection covers another selection

		If true, that means that backup dump created by current
		selection contains all objects from another selection, and so
		could be used.
		"""
		return True

	def __repr__(self):
		return 'DumpAll()'


DumpAll = pretty_yaml(DumpAll)


class DumpSelected(namedtuple('DumpSelected', ('resellers', 'clients', 'domains'))):
	def covers(self, selection):
		"""Check if this selection covers another selection

		If true, that means that backup dump created by current
		selection contains all objects from another selection, and so
		could be used.
		"""
		if isinstance(selection, DumpSelected):
			return (
				set(self.resellers) >= set(selection.resellers) and
				set(self.clients) >= set(selection.clients) and
				set(self.domains) >= set(selection.domains)
			)
		else:
			return False

	def __repr__(self):
		return "DumpSelected(%r, %r, %r)" % (
			self.resellers, self.clients, self.domains
		)

DumpSelected = pretty_yaml(DumpSelected)

class PmmMigrationAgentBase(object):

	def __init__(self, global_context, source_server):
		self.global_context = global_context
		self._source_server = source_server
		self.agent_dir = self._deploy()

	def create_dump(self, filename, is_archive_dump=False, selection=DumpAll()):
		dump_file = filename if not is_archive_dump else self.dump_file

		logger.debug(messages.RUN_PMM_AGENT_CREATE_DUMP_XML)
		self._run(dump_file, self.dump_log, selection)

		if is_archive_dump:
			logger.debug(messages.PACK_DUMP_XML_INTO_DUMP_ARCHIVE)
			with open(dump_file) as dump_xml_fp:
				save_backup_tar(dump_xml_fp.read(), filename)

	def create_shallow_dump(self, filename):
		logger.debug(messages.RUN_PMM_AGENT_CREATE_SHALLOW_DUMP)
		self._run_shallow(filename, self.dump_log)

	def create_capability_dump(self, filename, selection=DumpAll()):
		logger.debug(messages.RUN_PMM_AGENT_CREATE_CAPABILITY_DUMP)
		self._run_capability(filename, self.dump_log, selection)

	def check(self):
		raise NotImplementedError()

	def _run(self, dump_xml_filename, dump_log_filename, selection=DumpAll()):
		raise NotImplementedError()

	def _run_shallow(self, dump_xml_filename, dump_log_filename):
		raise NotImplementedError()

	def _run_capability(self, dump_xml_filename, dump_log_filename, selection=DumpAll()):
		raise NotImplementedError()

	def _deploy(self):
		raise NotImplementedError()

	def uninstall(self):
		raise NotImplementedError()

	@cached
	def _get_pmm_session_dir(self):
		return self.global_context.migrator_server.make_session_tmpdir('pmm-agent')

	@property
	def dump_file(self):
		return os.path.join(self._get_pmm_session_dir(), 'dump.xml')

	@property
	def dump_log(self):
		return os.path.join(self._get_pmm_session_dir(), 'dump.log')

	@property
	def check_report_file(self):
		return os.path.join(self._get_pmm_session_dir(), 'pre-migration.xml')

	@property
	def check_log_file(self):
		return os.path.join(self._get_pmm_session_dir(), 'pre-migration.log')
