from parallels.plesk.source.custom import messages
from parallels.core.utils.common import find_only


class HostingDescriptionModel(object):
	"""Object model over hosting description file, which describes hosting on custom panel that should be migrated"""

	def __init__(self, hosting_description_id, data):
		self._hosting_description_id = hosting_description_id
		self._data = data

	def iter_all_subscriptions(self):
		"""Iterate over subscriptions to be migrated

		:rtype: collections.Iterable[parallels.custom_panel_migrator.hosting_description.HostingDescriptionSubscription]
		"""
		for client_data in self._data:
			for subscription_data in client_data.get('subscriptions', []):
				yield HostingDescriptionSubscription(subscription_data)

	def get_subscription(self, name):
		"""Get subscription by name

		:type name: basestring
		:rtype: parallels.custom_panel_migrator.hosting_description.HostingDescriptionSubscription
		"""
		return find_only(
			self.iter_all_subscriptions(), lambda s: s.name == name,
			messages.FAILED_TO_FIND_SUBSCRIPTION_IN_DUMP % name
		)


class HostingDescriptionWebFilesMappingProvider(object):
	"""Base class for domain object (webspace, addon domain or subdomain) that provides web files mapping"""
	def __init__(self, data):
		self._data = data

	def iter_web_files(self):
		"""Iterate over web file mappings

		:rtype: collections.Iterable[HostingDescriptionWebFilesMapping]
		"""
		for web_file_data in self._data.get('web_files', []):
			yield HostingDescriptionWebFilesMapping(web_file_data)


class HostingDescriptionSubscription(HostingDescriptionWebFilesMappingProvider):
	"""Object model over subscription in hosting description file"""

	def __init__(self, data):
		super(HostingDescriptionSubscription, self).__init__(data)
		self._data = data

	@property
	def name(self):
		"""Name of the subscription

		:rtype: basestring
		"""
		return self._data['name']

	@property
	def source_document_root(self):
		"""Description of a path to document root (which is available by HTTP) on the source server

		:rtype: basestring | dict | None
		"""
		return self._data.get('source_document_root')

	@property
	def source_webspace_root(self):
		"""Description of a path to webspace root (which contains all web files of webspace) on the source server

		:rtype: basestring | dict | None
		"""
		return self._data.get('source_webspace_root')

	def iter_databases(self):
		"""Iterate over databases of that subscription

		:rtype: collections.Iterable[parallels.custom_panel_migrator.hosting_description.HostingDescriptionDatabase]
		"""
		for database_data in self._data.get('databases', []):
			yield HostingDescriptionDatabase(database_data)

	def iter_mailboxes(self):
		"""Iterate over mailboxes of that subscription

		:rtype: collections.Iterable[parallels.plesk.source.custom.hosting_description_model.HostingDescriptionMailbox]
		"""
		for mailbox_data in self._data.get('mailboxes', []):
			yield HostingDescriptionMailbox(mailbox_data)

	def iter_addon_domains(self):
		"""Iterate over addon domains of that subscription

		:rtype: collections.Iterable[parallels.plesk.source.custom.hosting_description_model.HostingDescriptionAddonDomain]
		"""
		for addon_domain_data in self._data.get('addon_domains', []):
			yield HostingDescriptionAddonDomain(addon_domain_data)

	def iter_subdomains(self):
		"""Iterate over subdomains of that subscription

		:rtype: collections.Iterable[parallels.plesk.source.custom.hosting_description_model.HostingDescriptionSubdomain]
		"""
		for subdomain_data in self._data.get('subdomains', []):
			yield HostingDescriptionSubdomain(subdomain_data)

	def get_addon_domain(self, name):
		"""Get addon domain by name

		:type name: basestring
		:rtype: parallels.custom_panel_migrator.hosting_description.HostingDescriptionAddonDomain
		"""
		return find_only(
			self.iter_addon_domains(), lambda d: d.name == name,
			messages.FAILED_TO_FIND_ADDON_IN_DUMP % name
		)

	def get_subdomain(self, name):
		"""Get subdomain by name

		:type name: basestring
		:rtype: parallels.custom_panel_migrator.hosting_description.HostingDescriptionSubdomain
		"""
		return find_only(
			self.iter_subdomains(), lambda d: d.name == name,
			messages.FAILED_TO_FIND_SUBDOMAIN_IN_DUMP % name
		)


class HostingDescriptionDatabase(object):
	"""Object model over database in hosting description file"""

	def __init__(self, data):
		self._data = data

	@property
	def db_type(self):
		"""Type of the database (either 'mysql' or 'mssql')

		:rtype: basestring
		"""
		return self._data.get('type', 'mysql')

	@property
	def name(self):
		"""Name of the database

		:rtype: basestring
		"""
		return self._data['name']

	@property
	def dump(self):
		"""Path to database dump file

		:rtype: basestring | None
		"""
		return self._data.get('dump')


class HostingDescriptionMailbox(object):
	"""Object model over mailbox in hosting description file"""

	def __init__(self, data):
		self._data = data

	@property
	def name(self):
		"""Full name of the mailbox

		:rtype: str
		"""
		return self._data['name']

	@property
	def short_name(self):
		"""Short name of the mailbox - everything before '@' symbol

		:rtype: str
		"""
		return self.name[:self.name.find('@')]

	@property
	def domain_name(self):
		"""Name of domain of the mailbox

		:rtype: str
		"""
		return self.name[self.name.find('@')+1:]

	@property
	def source_directory(self):
		"""Directory on the source server that contains mail messages (specific to Unix only)

		:rtype: basestring | None
		"""
		return self._data.get('directory')


class HostingDescriptionAddonDomain(HostingDescriptionWebFilesMappingProvider):
	"""Object model over addon domain in hosting description file"""

	def __init__(self, data):
		super(HostingDescriptionAddonDomain, self).__init__(data)
		self._data = data

	@property
	def name(self):
		"""Name of addon domain

		:rtype: str
		"""
		return self._data['name']

	@property
	def source_document_root(self):
		"""Description of a path to document root (which is available by HTTP) on the source server

		:rtype: basestring | dict | None
		"""
		return self._data.get('source_document_root')


class HostingDescriptionSubdomain(HostingDescriptionWebFilesMappingProvider):
	"""Object model over subdomain in hosting description file"""

	def __init__(self, data):
		super(HostingDescriptionSubdomain, self).__init__(data)
		self._data = data

	@property
	def name(self):
		"""Name of the subdomain

		:rtype: str
		"""
		return self._data['name']

	@property
	def source_document_root(self):
		"""Description of a path to document root (which is available by HTTP) on the source server

		:rtype: basestring | dict | None
		"""
		return self._data.get('source_document_root')


class HostingDescriptionWebFilesMapping(object):
	"""Object model over web files mapping in hosting description file"""

	def __init__(self, data):
		self._data = data

	@property
	def source(self):
		"""Source path of the web files to be copied

		:rtype: str | unicode
		"""
		return self._data['source']

	@property
	def target(self):
		"""Target path of the web files to be copied

		:rtype: str | unicode
		"""
		return self._data['target']

	@property
	def exclude(self):
		"""List of files to exclude

		:rtype: list[str | unicode]
		"""
		return self._data.get('exclude', [])

	@property
	def skip_if_source_not_exists(self):
		"""Whether to silently skip this item if source path does not exist on the source server

		:rtype: bool
		"""
		return self._data.get('skip_if_source_not_exists', False)
