from parallels.utils import cached


class ImportAPI(object):
	system_name = None  # Each API wrapper must specify the name of system whose API it wraps

	def has_addon_service_templates(self):
		"""Return True if target panel supports 
		addon service templates (service plans), False otherwise"""
		raise NotImplementedError()

	def create_reseller(self, reseller):
		"""Create reseller
		Return account identifier of the created reseller
		"""
		raise NotImplementedError()

	def create_customer(self, owner_id, customer):
		"""Create customer
		Return account identifier of the created customer
		"""
		raise NotImplementedError()

	def create_hosting_subscription(
		self, account_id, plan_id, addon_plan_ids, subscription, client=None, reseller=None
	):
		"""Create hosting subscription
		Return subscription identifier of the created subscription
		"""
		raise NotImplementedError()

	def sync_subscription(self, subscription_name):
		"""Syncronize subscription's limits and permissions 
		with current service template (service plan)
		"""
		raise NotImplementedError()

	def create_service_template(self, owner_login, plan_name, plan_settings):
		"""Create service template (service plan)"""
		raise NotImplementedError()

	def create_addon_service_template(self, owner_login, plan_name, plan_settings):
		"""Create addon service template (service plan)"""
		raise NotImplementedError()

	def get_service_template_info_list(self, service_template_ids):
		"""Get information for the specified service templates.
		Return list of service templates with their properties, including resources
		"""
		raise NotImplementedError()

	def get_service_template_list(self, owner_id, active=None):
		"""Get list of service templates which belong to specified account.
		Return list of service templates with only a minimal information such as identifier, name, status and description
		"""
		raise NotImplementedError()

	@cached
	def get_service_template_details_by_name(self, service_template_name, owner_username=None):
		"""
		Retrive service template details by name
		:param service_template_name: srting, service template name
		:param owner_username: string, reseller username, None for admin
		:return: parallels.common.import_api.model.BaseServiceTemplateDetails
		"""
		owner_id = None
		if owner_username is not None:
			for reseller in self.list_resellers([owner_username]):
				owner_id = reseller.id
				break

		service_template_id = None
		for service_template in self.get_service_template_list(owner_id):
			if service_template.name == service_template_name:
				service_template_id = service_template.st_id
		if service_template_id is None:
			# service template with given name is not found, so return None
			return None

		service_templates = self.get_service_template_info_list([service_template_id])
		if len(service_templates) < 1:
			return None
		return service_templates[0]

	def get_addon_service_template_list(self, owner_id, active=None):
		"""Get list of addon service templates which belong to specified account.
		Return list of service templates with only a minimal information such as identifier, name, status and description
		"""
		raise NotImplementedError()

	def list_resellers(self, reseller_logins):
		"""List admin's direct resellers with specified logins.
		Return list of resellers with their contact information
		"""
		raise NotImplementedError()

	def list_customers(self, customer_logins):
		"""List customers with specified logins. It is not important who their vendor is - admin or reseller.
		Return list of customers with their contact information (CustomerInfo data type)
		"""
		raise NotImplementedError()

	def list_hosting_subscriptions(self, account_ids):
		"""List hosting subscriptions of specified accounts.
		Return list of PPA subscriptions data, with resources information
		"""
		raise NotImplementedError()

	def list_webspaces(self, domain_names):
		"""List webspaces with specified domain names.
		"""
		raise NotImplementedError()

	def list_webspaces_brief(self, domain_names):
		"""Unlike listWebspaces method, this one does not retrieve information about webspace, when webspace is found.
		For the found webspaces, it returns only the minimal information - webspace_id and name.
		"""

	def create_webspace(self, subscription):
		"""Create webspace by model subscription data
		Return webspace_id
		"""
		raise NotImplementedError()

	def suspend_customer(self, account_id):
		"""Suspend a single customer"""
		raise NotImplementedError()

	def suspend_subscription(self, subscription_id):
		"""Suspend a single subscription"""
		raise NotImplementedError()

	def get_webspace_id_by_primary_domain(self, domain_name):
		"""Get webspace ID by primary domain's name"""
		raise NotImplementedError()

	def get_subscription_id_by_webspace_id(self, webspace_id):
		"""Get subscription ID by webpsace ID"""
		raise NotImplementedError()

	def change_sysuser_login(self, subscription_name, sysuser_login):
		"""Change login of a system user. Could raise exceptions: UserAlreadyExistsException, LoginIsInvalidException"""
		raise NotImplementedError()

	@staticmethod
	def repair_webspace_security(subscription):
		"""Repair Windows webspace security"""
		raise NotImplementedError()

	@staticmethod
	def get_dedicated_app_pool_user(subscription):
		"""Get name of dedicated application pool user for Windows webspace"""
		raise NotImplementedError()

	def refresh_node_components(self, node):
		"""Refresh service node components. If customer has just installed some component, 
		for example FrontPage extensions, we need to explicitly call refresh, 
		otherwise migration may fail because main node still 
		thinks there is no FrontPage on the node.
		
		Parameters:
		- node: instance of parallels.common.connections.subscription_nodes.SubscriptionNode"""
		raise NotImplementedError()

	def set_ip_access_restrictions(self, domain_name, ip_allow, ip_deny):
		raise NotImplementedError()

	def get_domain_dns_server_ips(self, target_server, domain_name):
		"""
		:type target_server: parallels.common.connections.target_servers.TargetServer
		"""
		raise NotImplementedError()


class UserAlreadyExistsException(Exception):
	pass


class LoginIsInvalidException(Exception):
	pass
