from collections import namedtuple
from contextlib import contextmanager
import logging

from parallels.utils import cached
from parallels.common import MigrationError
from parallels.common.connections.connections import Connections
from parallels.common.utils.config_utils import ConfigSection
from parallels.common.migrator_config import read_copy_mail_content_settings
from parallels.common.migrator_config import read_windows_agent_settings
from parallels.utils import obj
from parallels.utils import find_first
from parallels.helm3_migrator.server import Helm3SourceServer

logger = logging.getLogger(__name__)

class Helm3MigratorConnections(Connections):
	def __init__(self, config, target_panel, migrator_server):
		super(Helm3MigratorConnections, self).__init__(config, target_panel)
		self.helm3 = Helm3Connections(config, migrator_server)

	@cached
	def get_source_node(self, node_id):
		return Helm3SourceServer(
			node_id,
			self.get_information_servers()[node_id]
		)

	def get_information_servers(self):
		return {'helm3': self.helm3.get_main_source_server().node_settings}

Helm3Server = namedtuple('Helm3Server', (
	'id', 'ip', 'windows_auth', 'session_dir', 'is_windows', 'mail_settings', 'agent_settings'
))

class Helm3Connections:
	def __init__(self, config, migrator_server):
		self.source_servers = []
		source_server_settings = self._read_source_server_settings(config)
		for server_id, settings in source_server_settings.items():
			self.source_servers.append(
				Helm3SourceServer(server_id, settings, migrator_server)
			)

		section = ConfigSection(config, 'GLOBAL')
		self.resellers_list =  section.get('resellers-list', None)
		self.clients_list =  section.get('clients-list', None)

	@contextmanager
	def runner(self):
		"""Get runner of main Helm node"""

		with self.get_main_source_server().runner() as runner:
			yield runner

	def get_source_server_by_ip(self, ip):
		"""Get Helm source server by IP address"""

		server = find_first(
			self.source_servers, 
			lambda server: server.ip() == ip
		)
		if server is not None:
			return server
		else:
			raise MigrationError(
				"""Cannot find source server with IP '%s'.""" % ip
			)

	def get_source_server_by_id(self, server_id):
		"""Get Helm source server by ID from configuration file"""

		server = find_first(
			self.source_servers, 
			lambda server: server.node_id == server_id 
		)
		if server is not None:
			return server
		else:
			raise MigrationError(
				"""Cannot find source server with ID '%s'.""" % server_id
			)

	def get_main_source_server(self):
		"""Get Helm main source server"""

		return self.get_source_server_by_id('helm3')

	def _read_source_server_settings(self, config):
		"""Read configuration of Helm servers"""

		source_helm_servers_auth = {}
		list_str = config.get('GLOBAL', "source-helms")
		if list_str.strip() != '':
			source_sections = map(str.strip, list_str.split(','))
			helm3_section = ConfigSection(config, 'helm3')
			for section_name in source_sections:
				section = ConfigSection(config, section_name)
				mail_settings = read_copy_mail_content_settings(
					section, is_windows=True
				)
				source_helm_servers_auth[section_name] = Helm3Server(
					id=section_name,
					ip=section['ip'],
					windows_auth=obj(
						username=section.get('windows-username', helm3_section['windows-username']),
						password=section.get('windows-password', helm3_section['windows-password'])
					),
					session_dir=section.get('session-dir', 'c:\\migrator'),
					is_windows=True,
					mail_settings=mail_settings,
					agent_settings=read_windows_agent_settings(
						config, section_name
					)
				)

		return source_helm_servers_auth
