# standard python modules
import logging
import threading
import math

# import all local modules from the rest package
from . import *

class xMattersCollectionThread(object):

    # constructor
    def __init__(self, request):
        self.log = logging.getLogger(__name__)
        self.request = request

    def createCollection(self, data, max_threads, function):
        bucketSize = int(math.ceil(float(len(data)) / float(max_threads)))
        threads = []
        for n in range(max_threads):
            slice = data[n * int(bucketSize): (n + 1) * int(bucketSize)]
            if len(slice) > 0:
                process = threading.Thread(target=function, args=(n, slice, ))
                process.start()
                threads.append(process)

        # Join all threads before proceeding
        for process in threads:
            process.join()

        return process

class xMattersCollection(xMattersCollectionThread):

    # constructor
    def __init__(self, *args, **kwargs):
        super(xMattersCollection, self).__init__(*args, **kwargs)
        self.succeed = []
        self.fail = []

    # def to Create Groups
    def createGroupsCollection(self, data, max_threads):
        del self.succeed[:]  # first clear the list from previous process
        del self.fail[:]

        process = self.createCollection(data, max_threads, self.createGroups)
        # print('Returning List of Users Created: ' + str({'succeed': self.succeed, 'fail': self.fail}))
        return {'succeed': self.succeed, 'fail': self.fail}

    def createGroups(self, thread, data):
        xmGroup = xMattersGroup(self.request)
        for x in range(len(data)):
            self.log.debug('Thread number: ' + str(thread) + ' Creating Group: ' + data[x]['targetName'])
            response = xmGroup.createGroup(data[x])
            if (response):
                self.succeed.append(data[x]['targetName'])
            else:
                self.fail.append(data[x]['targetName'])

    # def to add Members
    def addMemberToShiftCollection(self, data, max_threads):
        del self.succeed[:]  # first clear the list from previous process
        del self.fail[:]

        process = self.createCollection(data, max_threads, self.addMembersToShift)
        # print('Returning List: ' + str({'succeed': self.succeed, 'fail': self.fail}))
        return {'succeed': self.succeed, 'fail': self.fail}

    def addMembersToShift(self, thread, data):
        xmShift = xMattersShift(self.request)
        for x in range(len(data)):
            self.log.debug('Thread number: ' + str(thread) + ' Adding Member: ' + data[x]['member'] + ' to Shift: '+data[x]['shift']+' in Group: ' + data[x]['name'])
            # print('Thread number: ' + str(thread) + ' Adding Member: ' + data[x]['member'] + ' to Shift: '+data[x]['shift']+' in Group: ' + data[x]['name'])
            response = xmShift.addMemberToShift(data[x]['name'], data[x]['shift'], data[x]['member'])
            if (response):
                self.succeed.append(data[x]['member'])
            else:
                self.fail.append(data[x]['member'])

    # def to Create Groups
    def removeGroupsCollection(self, data, max_threads):
        del self.succeed[:]  # first clear the list from previous process
        del self.fail[:]

        process = self.createCollection(data, max_threads, self.removeGroups)
        # print('Returning List of Groups Removed: ' + str({'succeed': self.succeed, 'fail': self.fail}))
        return {'succeed': self.succeed, 'fail': self.fail}

    def removeGroups(self, thread, data):
        xmGroup = xMattersGroup(self.request)
        for x in range(len(data)):
            self.log.debug('Thread number: ' + str(thread) + ' Removing Group: ' + data[x]['targetName'])
            response = xmGroup.removeGroup(data[x]['targetName'])
            if (response):
                self.succeed.append(data[x]['targetName'])
            else:
                self.fail.append(data[x]['targetName'])

    # def to Create Groups
    def createOrModifyGroupsCollection(self, data, max_threads):
        del self.succeed[:]  # first clear the list from previous process
        del self.fail[:]

        process = self.createCollection(data, max_threads, self.createOrModifyGroups)
        # print('Returning List of Groups Created or Modified: ' + str({'succeed': self.succeed, 'fail': self.fail}))
        return {'succeed': self.succeed, 'fail': self.fail}

    # function accepts an array of supervisor names and retrieves them
    def createOrModifyGroups(self, thread, data):
        xmGroup = xMattersGroup(self.request)
        xmPerson = xMattersPerson(self.request)
        for x in range(len(data)):
            self.log.debug('Thread number: ' + str(thread) + ' Creating Group: ' + data[x]['targetName'])
            # print('Thread number: ' + str(thread) + ' Creating Group: ' + data[x]['targetName'])
            # function accepts an array of supervisor names and retrieves them
            data[x]['supervisors'] = xmPerson.getPeopleIDs(data[x]['supervisors'])
            exist = xmGroup.getGroup(data[x]['targetName'])
            if (exist is None):
                response = xmGroup.createGroup(data[x])
            elif (exist):
                data[x]['id'] = exist['id']
                response = xmGroup.modifyGroup(data[x])
            if (response):
                self.succeed.append(data[x]['targetName'])
            else:
                self.fail.append(data[x]['targetName'])

    # def to Modify Persons
    def modifyPeopleCollection(self, data, max_threads):
        del self.succeed[:]  # first clear the list from previous process
        del self.fail[:]

        process = self.createCollection(data, max_threads, self.modifyPeople)
        # print('Returning List: ' + str({'succeed': self.succeed, 'fail': self.fail}))
        return {'succeed': self.succeed, 'fail': self.fail}

    def modifyPeople(self, thread, data):
        xmPerson = xMattersPerson(self.request)
        for x in range(len(data)):
            user = xmPerson.getPerson(data[x]['targetName'])
            if (user):
                data[x]['id'] = user['id']
                for role in user['roles']['data']:
                    data[x]['roles'].append(role['name'])
                self.log.debug('Thread number: ' + str(thread) + ' Modifying User: ' + data[x]['targetName'])
                # print('Thread number: ' + str(thread) + ' Modifying User: ' + data[x]['targetName'])
                response = xmPerson.modifyPerson(data[x])
                if (response):
                    self.succeed.append(data[x]['targetName'])
                else:
                    self.fail.append(data[x]['targetName'])
            else:
                self.fail.append(data[x]['targetName'])
