'''
Created on Apr 11, 2014

@author: mandy
'''
import MyFunctions
from DirNode import DirNode

class ComputeSpecInfo(object):

    def __init__(self, main):
        '''
        Constructor
        '''
        self.main = main
        self.scene = main.scene
        self.sceneRight = main.sceneRight
    
    def find_paths_with_cycles(self, path_so_far):
        node_just_added = path_so_far[-1]
        for neigh in list(self.main.role_adjmat[node_just_added].children):
            newcycle = path_so_far + [neigh]
            if neigh in path_so_far:
                cycle = set(newcycle[newcycle.index(neigh):])
                if cycle not in self.main.cycles:
                    self.main.cycles.append(cycle)
            else:
                self.find_paths_with_cycles(newcycle)
        
    def breadthFirstSearch(self, roleAdjDict, start):
        visited, queue = set(), [start]
        while queue:
            vertex = queue.pop(0)
            if vertex not in visited:
                visited.add(vertex)
                connected = vertex.parentNodes.union(vertex.childrenNodes)
                queue.extend(connected-visited)
        return visited
        
    def getNumRoles(self):
        return len(self.main.roleSet)
        
    def getNumUsers(self):
        return len(self.main.userSet)
        
    def getNumDirs(self):
        return len(self.main.dirSet)
    
    def getRoleSet(self):
        roleset = set(self.main.role_res_mat.keys()).union(set(self.main.role_adjmat.keys()))
        for r in self.main.role_adjmat.values():
            connection = r.parents.union(r.children)
            roleset = roleset.union(connection)
        for v in self.main.user_role_mat.values():
            roleset = roleset.union(v)
        return roleset
            
    def getUserSet(self):
        return set(self.main.user_role_mat.keys())
            
    def getDirSet(self):
        dirSet = set()
        for i in self.main.role_res_mat.keys():
            for k in self.main.role_res_mat[i].keys():
                parents = k.split('/')
                parents = filter(lambda a: a != '', parents)
                for j in xrange(len(parents)+1):
                    tempDir = '/'+'/'.join(parents[:j])
                    dirSet.add(tempDir)
        return dirSet
    
    def getPermStringFromList(self, permList):
        permStrList = []
        for p in permList:
            tempStr = ''
            for i in xrange(len(p)):
                tempStr+=p[i]
                if i!= len(p)-1:
                    tempStr+=','
            permStrList.append(tempStr)
        return permStrList
                
            
    def getObjPermForRole(self, key):
        objList = []
        permIter = []
        permissions = []
        permissionStrings = []
        completePermStringList = [[], []]
        
        res = self.main.role_res_mat.get(key)
        for key,value in res.iteritems():
            objList.append(key)
            permIter.append(value.recursive)
            permissions.append(list(value.perms))
        permissionStrings = self.getPermStringFromList(permissions)
        #print objList, permIter, permissions, permissionStrings

        for i in xrange(len(objList)):
            if permIter[i]:
                completePermStringList[0].append('-r '+objList[i])
            else:
                completePermStringList[0].append(objList[i])
            completePermStringList[1].append(permissionStrings[i])
        return objList, permIter, permissions, permissionStrings, completePermStringList
                
    def getAllParentNodesForRoleNode(self, r):
        parents = [r]
        r.allParentNodes = set([r])
        while parents!= []:
            currentrole = parents.pop(0)
            for p in currentrole.parentNodes:
                if p not in r.allParentNodes:
                    r.allParentNodes.add(p)
                    parents.append(p)
        r.allParentNodes.remove(r)
        
    def getAllChildrenNodesForRoleNode(self, r):
        children = [r]
        r.allChildrenNodes = set([r])
        while children!= []:
            currentrole = children.pop(0)
            for c in currentrole.childrenNodes:
                if c not in r.allChildrenNodes:
                    r.allChildrenNodes.add(c)
                    children.append(c)
        r.allChildrenNodes.remove(r)
            
    def getAllParentNodesForDirNode(self, d):
        parents = [d]
        while parents:
            vertex = parents.pop(0)
            d.allparents = d.allparents.union(vertex.parent)
            parents.extend(vertex.parent)
    
    def getAllChildrenNodesForDirNode(self, d):
        children = [d]
        while children:
            vertex = children.pop(0)
            d.allchildren = d.allchildren.union(vertex.children)
            children.extend(vertex.children)
            
    def getDirHierarchy(self, dirList):
        rootnode = DirNode('/', self.sceneRight)
        dirHier = [[rootnode]]
        dirNodeList = [rootnode]
        for d in dirList:
            if d!='/':
                node = DirNode(d, self.sceneRight)
                dirNodeList.append(node)
        dirNodeList = sorted(dirNodeList, key=lambda x: len(x.dir.split('/')))
        for n in dirNodeList:
            for p in dirNodeList:
                dirList1 = p.dir.split('/')
                dirList2 = n.dir.split('/')
                dirList1 = filter(lambda a: a != '', dirList1)
                dirList2 = filter(lambda a: a != '', dirList2)
                if p.dir != n.dir and MyFunctions.compareTwoLists(dirList1, dirList2):
                    if n.parent == []:
                        n.parent.append(p)
                    else:
                        parentList = n.parent[0].dir.split('/')
                        parentList = filter(lambda a:a!= '', parentList)
                        if len(parentList)<len(dirList1):
                            n.parent[0] = p
        for n in dirNodeList:
            for d in n.parent:
                d.children.append(n)
        tovisit = dirHier[0]
        while tovisit:
            nextlevel = set()
            for v in tovisit:
                nextlevel = nextlevel.union(set(v.children))
            tovisit = list(nextlevel)
            tovisit = sorted(tovisit, key=lambda d:d.dir)
            dirHier.append(tovisit)
#         for i in xrange(0, len(dirHier)):
#             for n in dirHier[i]:
#                 print i, n.dir
#                 print 'parent'
#                 for p in n.parent:
#                     print p.dir
#                 print 'children'
#                 for c in n.children:
#                     print c.dir
        for d in dirNodeList:
            self.getAllParentNodesForDirNode(d)
            self.getAllChildrenNodesForDirNode(d)
        return dirHier, dirNodeList