import logging
import xml.etree.ElementTree as et

from parallels.core.messages import LOG_EXCEPTION
from parallels.core.utils.common import ip, xml
from parallels.shcm_web_sn.shm_context import SHMContext

from parallels.shcm_web_sn.source.shcm_web_sn import messages

logger = logging.getLogger(__name__)


class MoveList(object):
	name = None
	web_ip_v4 = None
	web_ip_v4_type = None
	web_ip_v6 = None
	web_ip_v6_type = None
	src_ctx = None
	dst_ctx = None


def read_move_list(fileobj, move_list):
	"""Method reads move list from file object.
	Example of move list XML:
	<move>
		<webspace name="test.tld">
			<source-context><!--json_encoded_shcm_context--></source-context>
			<destination-context><!--json_encoded_shcm_context--></destination-context>
			<web-ip type="shared">10.58.1.1</web-ip>
			<web-ip type="shared">::1</web-ip>
		</webspace>
	</move>
	:type fileobj: file object
	:type move_list: parallels.shcm_web_sn.source.shcm_web_sn.move_list.MoveList
	:rtype: list
	"""
	errors = []

	try:
		root_node = et.fromstring(fileobj.read())
	except Exception as err:
		logger.debug(LOG_EXCEPTION, exc_info=True)
		errors.append(messages.FAILED_TO_READ_MOVE_LIST_FILE.format(msg=str(err)))
	else:
		webspace_elem = xml.multiple_find(root_node, ['webspace'])
		source_ctx_elem = xml.multiple_find(root_node, ['source-context'])
		destintation_ctx_elem = xml.multiple_find(root_node, ['destination-context'])

		try:
			if not webspace_elem or source_ctx_elem is None or destintation_ctx_elem is None:
				raise Exception(messages.REQUIRED_MOVE_LIST_NODES)

			_process_webspace(webspace_elem, move_list)

			move_list.src_ctx = SHMContext(source_ctx_elem.text)
			move_list.dst_ctx = SHMContext(destintation_ctx_elem.text)
		except Exception as e:
			errors.append(str(e))

	return errors

def _process_webspace(webspace_elem, move_list):
	"""
	:type webspace_elem: xml.etree.ElementTree.Element
	:type move_list: parallels.shcm_web_sn.source.shcm_web_sn.move_list.MoveList
	"""
	# Get webspace name
	move_list.name = webspace_elem.attrib.get('name')
	if move_list.name is None:
		raise Exception(messages.ATTRIBUTE_NAME_OF_WEBSPACE_NODE_MUST_BE_SET)

	if move_list.name.strip() == '':
		raise Exception(messages.ATTRIBUTE_NAME_OF_WEBSPACE_NODE_CAN_NOT_BE_EMPTY)

	# Get webspace IPs
	for web_ip_elem in xml.multiple_findall(webspace_elem, ['web-ip']):
		target_ip = web_ip_elem.text
		if target_ip is None or target_ip.strip() == '':
			raise Exception(messages.TARGET_WEB_SERVICE_NODE_IP_NOT_SPECIFIED.format(name=move_list.name))

		target_ip_type = web_ip_elem.attrib.get('type')
		if target_ip_type not in [u'shared', u'exclusive']:
			raise Exception(messages.TARGET_IP_HAS_INVALID_TYPE.format(ip=target_ip, ip_type=target_ip_type))

		if ip.is_ipv4(target_ip):
			move_list.web_ip_v4 = target_ip
			move_list.web_ip_v4_type = target_ip_type
		elif ip.is_ipv6(target_ip):
			move_list.web_ip_v6 = target_ip
			move_list.web_ip_v6_type = target_ip_type
		else:
			raise Exception(messages.TARGET_WEB_SERVICE_NODE_IP_NOT_VALID.format(ip=target_ip, domain=move_list.name))
