import logging
from contextlib import contextmanager

from parallels.core import messages
from parallels.core.connections.ssh.server_connection.base import BaseSSHServerConnection

logger = logging.getLogger(__name__)


class NestedContextSSHServerConnection(BaseSSHServerConnection):
	"""Connection to server opened in "with" block, closed on exit of the most outer "with" block

	When you get out of the most outer "with" block, connection is
	automatically closed. There is no need to close connection explicitly.
	"""

	@contextmanager
	def ssh(self):
		"""Get raw SSH handle to the server

		:rtype paramiko.SSHClient
		"""
		if self._ssh is None:
			logger.debug(messages.DEBUG_OPEN_SSH_CONNECTION, self._node_description)
			with self._connect_ssh() as ssh_object:
				self._ssh = ssh_object
				try:
					yield self._ssh
				finally:
					self._ssh = None
					logger.debug(messages.CLOSE_SSH_CONNECTION_S_1, self._node_description)
		else:
			# SSH connection is already initialized by top-level contexts, no need to recreate it in nested contexts
			# It will be closed in top-level context too, so there is no need to close connection here
			logger.debug(messages.SSH_CONNECTION_S_IS_ALREADY_OPENED, self._node_description)
			yield self._ssh

	def close(self):
		"""Close connection to the SSH server

		Actually no explicit close is necessary.
		Connection is closed automatically
		when gets out of the most outer "with" block for
		"runner" or "ssh" methods

		:rtype None
		"""
		pass
