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


def setProductActionRequestForHostGroup(self, hostGroupId, productId, actionRequest):
    depotsWithClients = self._getClientsOnDepotByHostGroup(hostGroupId)
    for depotid in depotsWithClients:
        if not self._isProductOnDepot(productId, depotid):
            raise Exception('Product "%s" not found on depot server "%s".' % (productId, depotid))

        self._updateActionRequestOnClients(depotsWithClients[depotid], productId, actionRequest)


def _getClientsOnDepotByHostGroup(self, hostGroupId):
    clientsInGroup = self._getClientsInHostGroup(hostGroupId)
    logger.debug('Group %s has the following clients: %s' % (hostGroupId, clientsInGroup, ))
    depotsWithClients = self._getClientsOnDepots(clientsInGroup)
    logger.debug('The clients are using the following depots: %s' % (depotsWithClients, ))

    return depotsWithClients


def _getClientsInHostGroup(self, hostGroupId):
    return [c.objectId for c in self._backend.objectToGroup_getObjects(groupId=hostGroupId, groupType="HostGroup")]


def _getClientsOnDepots(self, clientIds):
    """Returns a dict where the depot is the key and the value a list of clients."""
    clientsOnDepot = {}

    for depotClientHash in self._backend.configState_getClientToDepotserver(clientIds=clientIds):
        try:
            clientsOnDepot[depotClientHash['depotId']].append(depotClientHash['clientId'])
        except KeyError:
            clientsOnDepot[depotClientHash['depotId']] = [depotClientHash['clientId']]

    logger.debug('Found the following clients on depots: %s' % (clientsOnDepot, ))
    return clientsOnDepot


def _isProductOnDepot(self, productId, depotId):
    if self._backend.productOnDepot_getObjects(productId=productId, depotId=depotId):
        return True
    else:
        return False


def _updateActionRequestOnClients(self, clients, productId, actionRequest):
    productOnClients = self._backend.productOnClient_getObjects(clientId=clients, productId=productId)
    not_updated_clients = set(clients)

    for poc in productOnClients:
        poc.setActionRequest(actionRequest)
        not_updated_clients.remove(poc.clientId)
        logger.debug('ActionRequest "%s" was set on client "%s".' % (actionRequest, poc.clientId))

    self._backend.productOnClient_updateObjects(productOnClients)

    if not_updated_clients:
        product_type = self._backend.product_getObjects(id=productId)[0].getType()
        [self._backend.productOnClient_create(productId, product_type, client, actionRequest=actionRequest) for client in not_updated_clients]


def setProductActionRequestForProductGroup(self, hostGroupId, productGroupId, actionRequest):
    depotsWithClients = self._getClientsOnDepotByHostGroup(hostGroupId)

    for product_group_mapping in self._backend.objectToGroup_getObjects(groupType='ProductGroup', groupId=productGroupId):
        productId = product_group_mapping.objectId

        for depotid in depotsWithClients:
            if not self._isProductOnDepot(productId, depotid):
                raise Exception('Product "%s" not found on depot server "%s".' % (productId, depotid))

            self._updateActionRequestOnClients(depotsWithClients[depotid], productId, actionRequest)


def setProductPropertyForHostGroup(self, productId, propertyId, propertyValue, groupId):
    clientsInGroup = [c.objectId for c in self._backend.objectToGroup_getObjects(groupId=groupId, groupType="HostGroup")]
    productPropertyStates = self._backend.productPropertyState_getObjects(objectId=clientsInGroup, productId=productId, propertyId=propertyId)
    clientsWithoutProperty = set(clientsInGroup)

    for productPropertyState in productPropertyStates:
        productPropertyState.setValues(propertyValue)
        clientsWithoutProperty.remove(productPropertyState.objectId)

    self._backend.productPropertyState_updateObjects(productPropertyStates)

    [self._backend.productPropertyState_create(productId, propertyId, client, values=propertyValue) for client in clientsWithoutProperty]


def getPossibleImagefileValuesForHostGroup(self, groupId):
    def addClientToProduct(clientId, productId):
        try:
            productsWithClients[productId].add(clientId)
        except KeyError:
            productsWithClients[productId] = set([clientId])

    productId = 'opsi-local-image-restore'
    propertyId = 'imagefiles_list'

    clientsInGroup = self._getClientsInHostGroup(groupId)
    productPropertyStates = self._backend.productPropertyState_getObjects(objectId=clientsInGroup, productId=productId, propertyId=propertyId)

    productsWithClients = {}
    for productPropertyState in productPropertyStates:
        for key in productPropertyState.values:
            if u',' in key:
                # This is the workaround for a bug where the list of
                # images will become a comma-seperated string instead of
                # a list of strings.
                for key_part in key.split(u','):
                    addClientToProduct(productPropertyState.objectId, key_part)
            else:
                addClientToProduct(productPropertyState.objectId, key)

    clientSet = set(clientsInGroup)
    return [product for product in productsWithClients if clientSet == productsWithClients[product]]

def groupname_exists(self, groupId):
    if self.group_getObjects(id=groupId):
        return True
    else:
        return False


def group_rename(self, oldGroupId, newGroupId):
    oldGroupId = forceUnicode(oldGroupId)
    newGroupId = forceUnicode(newGroupId)

    if self.groupname_exists(newGroupId):
        raise Exception(u'Group "{0}" already defined.'.format(newGroupId))

    if not self.groupname_exists(oldGroupId):
        raise Exception(u'Old Group "{0}"" not exists.'.format(oldGroupId))
    
    oldGroup = self.group_getObjects(id=oldGroupId)[0]
    self.group_createHostGroup(
        id=newGroupId, 
        description=oldGroup.description, 
        notes=oldGroup.notes, 
        parentGroupId=oldGroup.parentGroupId
    )
    
    for group in self.group_getObjects(parentGroupId=oldGroupId):
        group.parentGroupId = newGroupId
        self.group_updateObject(group)

    for oldObjToGrp in self.objectToGroup_getObjects(groupId=oldGroupId):
        self.objectToGroup_create(
            groupType=oldObjToGrp.groupType,
            groupId=newGroupId,
            objectId=oldObjToGrp.objectId
        )
        self.objectToGroup_delete(
            groupType=oldObjToGrp.groupType,
            groupId=oldGroupId,
            objectId=oldObjToGrp.objectId
        )
        
    self.group_delete(id=oldGroupId)
   