from parallels.core import messages
import posixpath
from pipes import quote
from parallels.core.registry import Registry
import re


def is_debian(runner):
	result = runner.run("/bin/sh", ["-c", '/usr/bin/test -f /etc/debian_version && echo "yes" || echo "no"']).strip()
	if result == "yes":
		return True
	elif result == "no":
		return False
	else:
		raise Exception(messages.FAILED_DETECT_OS_INVALID_OUTPUT_S % (result,))


def is_centos(runner):
	result = runner.run("/bin/sh", ["-c", '/usr/bin/test -f /etc/redhat-release && echo "yes" || echo "no"']).strip()
	if result == "yes":
		return True
	elif result == "no":
		return False
	else:
		raise Exception(messages.FAILED_DETECT_OS_INVALID_OUTPUT_S_1 % (result,))


def is_suse(runner):
	result = runner.run("/bin/sh", ["-c", '/usr/bin/test -f /etc/SuSE-release && echo "yes" || echo "no"']).strip()
	if result == "yes":
		return True
	elif result == "no":
		return False
	else:
		raise Exception(messages.FAILED_DETECT_OS_INVALID_OUTPUT_S_2 % (result,))


def map_copy_owner_user(runner_source, runner_target, source_basedir, target_basedir, owner_from, owner_to):
	"""For each file on source node located in 'source_basedir' and owned by user 'owner_from' 
	change user to 'owner_to' on target node in 'target_basedir'"""
	_map_copy_owner(
		runner_source, runner_target, source_basedir, target_basedir, owner_from, owner_to, "user", "/bin/chown"
	)


def map_copy_owner_group(runner_source, runner_target, source_basedir, target_basedir, owner_from, owner_to):
	"""For each file on source node located in 'source_basedir' and owned by group 'owner_from' 
	change group to 'owner_to' on target node in 'target_basedir'"""
	_map_copy_owner(
		runner_source, runner_target, source_basedir, target_basedir, owner_from, owner_to, "group", "/bin/chgrp"
	)


def _map_copy_owner(
	runner_source, runner_target, source_basedir, target_basedir, owner_from, owner_to, find_criteria, change_command
):
	filenames = [
		filename for filename in runner_source.run(
			'/usr/bin/find', [source_basedir, '-%s' % (find_criteria,), owner_from, '-printf', r'%P\n']
		).splitlines() 
		if filename != ''
	]
	for filename in filenames:
		target_filename = posixpath.join(target_basedir, filename)
		if file_exists(runner_target, target_filename):
			runner_target.run(
				change_command, [owner_to, target_filename]
			)


def format_command(template, *args, **kw):
	qargs = map(quote, args)
	qkw = dict((k, quote(unicode(v))) for k, v in kw.iteritems())
	return unicode(template).format(*qargs, **qkw)


def format_command_list(cmd, args):
	return " ".join([
		quote(arg) for arg in [cmd] + ([] if args is None else args)
	])


def file_exists(runner, filepath):
	exit_code, _, _ = runner.run_unchecked('/usr/bin/test', ['-e', filepath])
	return exit_code == 0


def get_files_list(runner, path):
	files = runner.sh('find {path} -maxdepth 1 -type f -printf "%f\\0"'.format(path=path)).split("\0")
	return [item for item in files if item]


def upload_file_content_linux(server, filename, content):
	"""Upload file contents.

	File is created in server's remote session dir, if one exists, or in '/tmp'
	otherwise.
	"""
	context = Registry.get_instance().get_context()
	full_filename = context.migrator_server.get_session_file_path(filename)
	with context.migrator_server.runner() as runner:
		runner.upload_file_content(full_filename, content)
	with server.runner() as runner:
		if hasattr(server, 'get_session_file_path'):
			remote_filepath = server.get_session_file_path(filename)
			remote_filename = get_safe_filename(runner, remote_filepath)
		else:
			remote_filename = get_safe_filename(runner, "/tmp/%s_XXXXXX" % filename)
		runner.upload_file(full_filename, remote_filename.strip())
		runner.sh(u'chmod 600 "%s"' % remote_filename)
	return remote_filename


def get_safe_filename(runner, filename_stem):
	"""Create a temporary file with 600 access rights."""
	return runner.sh(u'mktemp "%s_XXXXXX"' % filename_stem).strip()

def get_apache_httpd_conf(runner):
	try:
		# Detect apache httpd.conf. In all systems it can be in different places. Therefore, we use the setting
		# of running apache.
		apache_process = runner.sh(u'ps -ef | grep "apache2\|httpd" | grep -v grep').splitlines()[0]
		httpd = re.search(r'(([^\s]+\s*){8}([^\s]+).*)', apache_process).group(2)
		_server_config_file = runner.sh(u'%s -V | grep SERVER_CONFIG_FILE' % httpd).strip()
		server_config_file = re.search(r'(.*)SERVER_CONFIG_FILE=(.*)', _server_config_file).group(2).strip('"')
		_httpd_root = runner.sh(u'%s -V | grep HTTPD_ROOT' % httpd).strip()
		httpd_root = re.search(r'(.*)HTTPD_ROOT=(.*)', _httpd_root).group(2).strip('"')
		apache_httpd_conf = posixpath.join(httpd_root, server_config_file)
		if not file_exists(runner, apache_httpd_conf):
				return None
		return apache_httpd_conf
	except:
		return None

def get_apache_user(runner, apache_httpd_conf):
	try:
		if apache_httpd_conf is None:
				return None

		result = runner.sh(u"grep -i '^user\s' %s" % apache_httpd_conf)
		user = re.search(r'[^\s]+\s*([^\s]+).*', result).group(1)
		exit_code, _, _ = runner.sh_unchecked(u"grep '^%s:' /etc/passwd" % user)
		if exit_code != 0:
			return None
		return user
	except:
		return None


def get_apache_group(runner, apache_httpd_conf):
	try:
		if apache_httpd_conf is None:
				return None

		result = runner.sh(u"grep -i '^group\s' %s" % apache_httpd_conf)
		group = re.search(r'[^\s]+\s*([^\s]+).*', result).group(1)
		exit_code, _, _ = runner.sh_unchecked(u"grep '^%s:' /etc/group" % group)
		if exit_code != 0:
				return None
		return group
	except:
		return None