from collections import namedtuple
import os
import logging
from parallels.common.utils.yaml_utils import pretty_yaml

from parallels.utils import cached
from parallels.common.plesk_backup 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._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(u"Run PMM agent to create dump XML")
		self._run(dump_file, self.dump_log, selection)

		if is_archive_dump:
			logger.debug(u"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(u"Run PMM agent to create shallow dump XML")
		self._run_shallow(filename, self.dump_log)

	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 _deploy(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')
