import logging
import subprocess
import sys
import os
from pipes import quote

logger = logging.getLogger(__name__)


class MigrationError(Exception):
	pass


class MigrationConfigurationFileError(Exception):
	pass


class MigrationNoContextError(Exception):
	pass


def run_and_check_local_command(command, stdin_content=None, output_codepage='utf-8'):
	exit_code, stdout_str, stderr_str = local_command_exec(command, stdin_content, output_codepage)
	if exit_code != 0:
		raise MigrationError(u"Failed to execute command '%s', non-zero exit code" % (u" ".join([quote(c) for c in command])))
	return stdout_str, stderr_str


def local_command_exec(command, stdin_content=None, output_codepage='utf-8', error_policy='strict', env=None):
	if type(command) is list or type(command) is tuple:
		command_str = ' '.join([quote(c) for c in command])
		command_encoded = [c.encode('utf-8') for c in command]
	else:
		command_str = command
		command_encoded = command.encode('utf-8')
	logger.debug(u"Call local command: %s" % command_str)

	command_env = os.environ.copy()
	command_env['LANG'] = 'en_US.utf-8'
	if env is not None:
		command_env.update(env)

	try:
		p = subprocess.Popen(
			command_encoded,
			stdin=subprocess.PIPE,
			stdout=subprocess.PIPE,
			stderr=subprocess.PIPE,
			env=command_env
		)
		stdout_str, stderr_str = [s.decode(output_codepage, error_policy) for s in p.communicate(stdin_content)]
		logger.debug(u"Command stdout: %s", stdout_str)
		logger.debug(u"Command stderr: %s", stderr_str)
		logger.debug(u"Command exit code: %s", p.returncode)
		return p.returncode, stdout_str, stderr_str
	except Exception as e:
		logger.debug(u'Exception:', exc_info=e)
		raise Exception(
			u"Failed to execute local command '%s': %s" % (u" ".join([quote(c) for c in command]), e)
		), None, sys.exc_info()[2]


def version_tuple(version):
	"""Convert string product version to a tuple of ints"""
	return tuple(map(int, version.split('.')))