# -*- coding: utf-8 -*-

def setProductActionRequestWithDependencies(self, productId, clientId, actionRequest, force=None):
	if force is not None:
		logger.warning("The 'force' parameter is deprecated and will not have any effect anymore. It may be removed in future versions.")
	productId = forceProductId(productId)
	clientId = forceHostId(clientId)
	actionRequest = forceActionRequest(actionRequest)
	depotId = self.getDepotId(clientId=clientId)
	if not self.productOnDepot_getObjects(depotId=depotId, productId=productId):
		raise BackendMissingDataError("Product '%s' not found on depot '%s'" % (productId, depotId))

	productOnClients = []
	pocExists = False
	productOnClients = self._backend.productOnClient_getObjects(clientId=clientId)
	foundProductOnClients = []

	for poc in productOnClients	:
		if poc.productId == productId:
			logger.debug(u"productOnClient for requested product found, updating")
			if poc.getActionRequest() != actionRequest:
				poc.setActionRequest(actionRequest)
			pocExists = True
		foundProductOnClients.append(poc)

	if not pocExists:
		logger.debug(u"requested productOnClient object does not exist, creating")
		foundProductOnClients.append(ProductOnClient(
			productId=productId,
			productType='LocalbootProduct',
			clientId=clientId,
			installationStatus='not_installed',
			actionRequest=actionRequest))

	productOnClients = self._backend.productOnClient_addDependencies(foundProductOnClients)
	if productOnClients:
		self._backend.productOnClient_updateObjects(productOnClients)


def userIsReadOnlyUser(self):
	return self.accessControl_userIsReadOnlyUser()


def getServiceTime(self, utctime=False):
	import datetime

	if utctime:
		return str(datetime.datetime.utcnow())
	else:
		return str(datetime.datetime.now())


def getSoftwareAuditDataCount(self):
	"""Get the count of data relevant to the software audit."""
	return len(self.auditSoftware_getObjects()) + len(self.auditSoftwareOnClient_getObjects())


def getHardwareAuditDataCount(self):
	"""Get the count of data relevant to the hardware audit."""
	return len(self.auditHardware_getObjects()) + len(self.auditHardwareOnHost_getObjects())


def getProductOrdering(self, depotId, sortAlgorithm=None):
	import OPSI.SharedAlgorithm

	if not sortAlgorithm:
		sortAlgorithm = "algorithm2"
		configs = self.config_getObjects(id="product_sort_algorithm")
		if configs and ("algorithm1" in configs[0].getDefaultValues()):
			sortAlgorithm = "algorithm1"

	logger.notice(u'Using sort algorithm {0!r}'.format(sortAlgorithm))

	productsByIdAndVersion = {}
	for product in self.product_getObjects(type="LocalbootProduct"):
		if product.id not in productsByIdAndVersion:
			productsByIdAndVersion[product.id] = {}
		if product.productVersion not in productsByIdAndVersion[product.id]:
			productsByIdAndVersion[product.id][product.productVersion] = {}

		productsByIdAndVersion[product.id][product.productVersion][product.packageVersion] = product

	productsDependenciesByIdAndVersion = {}
	for productDependency in self.productDependency_getObjects(productAction="setup"):
		if productDependency.productId not in productsDependenciesByIdAndVersion:
			productsDependenciesByIdAndVersion[productDependency.productId] = {}
		if productDependency.productVersion not in productsDependenciesByIdAndVersion[productDependency.productId]:
			productsDependenciesByIdAndVersion[productDependency.productId][productDependency.productVersion] = {}
		if productDependency.packageVersion not in productsDependenciesByIdAndVersion[productDependency.productId][productDependency.productVersion]:
			productsDependenciesByIdAndVersion[productDependency.productId][productDependency.productVersion][productDependency.packageVersion] = []

		productsDependenciesByIdAndVersion[productDependency.productId][productDependency.productVersion][productDependency.packageVersion].append(productDependency)

	availableProducts = []
	productDependencies = []
	productIds = []
	for productOnDepot in self.productOnDepot_getObjects(depotId=depotId, productType="LocalbootProduct"):
		product = productsByIdAndVersion.get(productOnDepot.productId, {}).get(productOnDepot.productVersion, {}).get(productOnDepot.packageVersion)
		if not product:
			continue
		availableProducts.append(product)
		productIds.append(product.id)
		if not product.setupScript:
			continue
		productDependencies.extend(productsDependenciesByIdAndVersion.get(productOnDepot.productId, {}).get(productOnDepot.productVersion, {}).get(productOnDepot.packageVersion, []))

	productIds.sort()

	if sortAlgorithm == "algorithm1":
		sortedList = OPSI.SharedAlgorithm.generateProductSequence_algorithm1(availableProducts, productDependencies)
	else:
		sortedList = OPSI.SharedAlgorithm.generateProductSequence_algorithm2(availableProducts, productDependencies)

	return {
		"not_sorted": productIds,
		"sorted": sortedList
	}

def setRights(self, path=None):
	"""
	Setting rights for a specified path.
	If no path is given it will try to set the rights for the current depot.

	The current implementation requires "sudo opsi-setup --patch-sudoers-file"
	to be run before.
	"""
	import os
	import subprocess

	if path is None:
		oldDepotPath = u'/opt/pcbin/install/'
		newDepotPath = u'/var/lib/opsi/depot/'
		try:
			if os.path.exists(newDepotPath) and os.path.islink(newDepotPath):
				linkedPath = os.readlink(newDepotPath)
				if os.path.isabs(linkedPath):
					path = linkedPath
				else:
					path = os.path.join(os.path.dirname(newDepotPath), linkedPath)
			else:
				path = oldDepotPath
		except OSError as oserr:
			if 'operation not permitted' in str(oserr).lower():
				path = oldDepotPath
			else:
				raise oserr

	if not os.path.exists(path):
		raise Exception('The path "{0}" does not exist.'.format(path))

	logger.debug('Going to set rights for path "{0}"'.format(path))
	callResult = subprocess.call(['sudo', 'opsi-set-rights', path])
	logger.debug('Finished setting rights. Exit Code: {0}'.format(callResult))

	if callResult:
		raise Exception("Setting rights on {0} failed. Did you run "
						"'opsi-setup --patch-sudoers-file'?".format(path))

	return 'Changing rights at "{0}" successful.'.format(path)
