'''
Accessible Access Control 1.0
2012-2104 Michigan Technological University
Supported in part by NSF grants: DUE-1140512, DUE-1245310 and IIS-1319363
Developer: Man Wang
Advisors:Dr. Steve Carr, Dr. Jean Mayo, Dr. Ching-Kuang Shene and Dr. Chaoli Wang
'''
'''
Created on Oct 13, 2013

@author: mandy
'''
import random, colorsys, re
import itertools
from PyQt4.QtGui import QMessageBox, QFont
from collections import namedtuple

SecurityLevel = namedtuple('SecurityLevel', ('clearance', 'categoryset'))
'''Permissions'''
def convertOctToRWXString(perm):
    perms = ''
#     if bool(perm&0b100):
#         perms+='r'
#     else:
#         perms+='-'
    if bool(perm&0b010):
        perms+='r'
    else:
        perms+='-'
    if bool(perm&0b001):
        perms+='w'
    else:
        perms+='-'
    return perms

'''general'''
def setFontForUI(widget, size=20):
        import platform
        operSys = platform.system()
        if operSys == 'Linux':
            font = widget.font()
            font.setPointSize(size)
            widget.setFont(font)
        elif operSys == 'Darwin':
            font = QFont('Courier', size)
            widget.setFont(font)
        
class Functions(object):
    
    def __init__(self):
        return 
    
    @staticmethod
    def makeSecurityLevel(clearance = None, categoryset=set()):
        if clearance is None:
            return None
        else:
            return SecurityLevel(clearance, categoryset)
        
    @staticmethod
    def securityLevelName(securityLevel):
        return securityLevel.clearance+',set('+','.join(securityLevel.categoryset)+')'
    
    @staticmethod
    def colorMapping(clearance, allclr):
        #assumes hue [0, 360), saturation [0, 100), lightness [0, 100)
        if allclr != []:
            numClr = len(allclr)
            intvl = 360 / (numClr)
            for i in xrange(0, numClr):
                if clearance == allclr[numClr-i-1]:
                    hue = i*intvl
        saturation = 90 + random.random() * 10;
        lightness = 50 + random.random() * 10;
        color = colorsys.hls_to_rgb(hue/360.0, lightness/100.0, saturation/100.0)
        color0 = color[0]*255
        color1 = color[1]*255
        color2 = color[2]*255
        return color0 ,color1, color2
    
    @staticmethod
    def addPredsToClearanceNode(node, latticenodes):
#         for ele in node.tempPreds:
#             for e in latticenodes:
#                 if e.name == ele:
#                     node.addPredecessor(e)
#                     break
        for k in latticenodes:
            Functions.addDirectPred(node, k)
                
    @staticmethod      
    def addSuccesToClearanceNode(node, latticenodes):
#         for ele in node.tempSucces:
#             for e in latticenodes:
#                 if e.name == ele:
#                     node.addSuccessor(e)
#                     break
        for k in latticenodes:
            Functions.addDirectSucc(node, k)
                
    @staticmethod              
    def getAllClearanceLevels(line):
        tmpline = line.replace(" ", "")
        index = tmpline.find('#')
        if index != -1:
            tmpline = tmpline[tmpline.find(':')+1:index]
        else:
            tmpline = tmpline[tmpline.find(':')+1:tmpline.find('\n')]
        if tmpline.find('<')!= -1:
            return tmpline.split('<')
        else:
            QMessageBox.critical(None, 'Error', 'Please make sure the Clearances are joined using "<" in import file')
            return []
            
    @staticmethod          
    def getAllCategory(line):
        tmpline = line.replace(" ", "")
        index = tmpline.find('#')
        if index != -1:
            tmpline = tmpline[tmpline.find(':')+1:index]
        else:
            tmpline = tmpline[tmpline.find(':')+1:tmpline.find('\n')]
        return tmpline.split(',')
          
    @staticmethod
    def combinations(iterable, r, cate):
        outputlist = []
        n = len(iterable)
        for indices in itertools.permutations(range(n), r):
            onelist = []
            if sorted(indices) == list(indices):
                for i in indices:
                    onelist.append(iterable[i])
                if cate in onelist:
                    outputlist.append(onelist)
        return outputlist
        
    @staticmethod
    def allNewCateCombination(categories,cate):
        allCombinations = []
        for i in xrange(0,len(categories)):
            onelength = Functions.combinations(categories, i+1, cate)
            for n in onelength:
                allCombinations.append(n)
        return allCombinations
    
    @staticmethod
    def allcombinations(iterable, r):
        outputlist = []
        n = len(iterable)
        for indices in itertools.permutations(range(n), r):
            onelist = []
            if sorted(indices) == list(indices):
                for i in indices:
                    onelist.append(iterable[i])
                outputlist.append(onelist)
        return outputlist
    
    @staticmethod
    def allCateCombination(categories):
        allCombinations = []
        for i in xrange(0,len(categories)+1):
            onelength = Functions.allcombinations(categories, i)
            for n in onelength:
                allCombinations.append(n)
        return allCombinations
    
    @staticmethod
    def nameOnlyContainLetters(name):
        if re.match("^[A-Za-z0-9]*$", name):
            return True
        return False
    
    @staticmethod
    def isSublist(list1, list2):
        if list2 == ['']:
            return True
        isSub = True
        for e in list2:
            if e not in list1:
                isSub = False
        return isSub
    
    @staticmethod
    def getKeyByValue(dictionary, searchItem):
        for key, value in dictionary.items():
            if searchItem in value:
                return key
        return -1
    
    @staticmethod
    def checkNameDuplication(name, checklist):
        for t in checklist:
            if t == name:
                return True
        return False
    
    @staticmethod 
    def checkPred(mainNode, node2):
        if node2 in mainNode.parent:
            return
        if mainNode.flgClr == node2.flgClr and len(node2.category) == len(mainNode.category)+1:
            if Functions.isSublist(node2.category, mainNode.category):
                mainNode.parent.append(node2)
        elif mainNode.flgClr < node2.flgClr:
            if len(node2.category) - len(mainNode.category) <= 1:
                if Functions.isSublist(node2.category, mainNode.category):
                    mainNode.parent.append(node2)
                    
    @staticmethod            
    def checkSucc(mainNode, node2):
        if node2 in mainNode.children:
            return
        if mainNode.flgClr == node2.flgClr and len(node2.category) == len(mainNode.category)-1:
            if Functions.isSublist(mainNode.category, node2.category):
                mainNode.children.append(node2)
        elif mainNode.flgClr > node2.flgClr:
            if len(mainNode.category) - len(node2.category) <= 1:
                if Functions.isSublist(mainNode.category, node2.category):
                    mainNode.children.append(node2)
        
    @staticmethod 
    def checkPred1(clr,cate, flgClr, category):
        if clr == flgClr and len(category) == len(cate)+1:
            if Functions.isSublist(category, cate):
                return True
        elif clr < flgClr:
            if len(category) <= len(cate):
                if Functions.isSublist(category, cate):
                    return True
        
                    
    @staticmethod            
    def checkSucc1(clr,cate, flgClr, category):
        if clr == flgClr and len(category) == len(cate)-1:
            if Functions.isSublist(cate, category):
                return True
        elif clr > flgClr:
            if len(cate) <= len(category):
                if Functions.isSublist(cate, category):
                    return True
                    
    @staticmethod 
    def addDirectPred(mainNode, node2):
        if node2.category == ['']:
            cate = []
        else:
            cate = node2.category
        if mainNode.category == ['']:
            cate1 = []
        else:
            cate1 = mainNode.category 
        if mainNode.flgClr == node2.flgClr and len(cate) == len(cate1)+1:
            if Functions.isSublist(node2.category, mainNode.category):
                mainNode.parent.append(node2)
        if (mainNode.flgClr == node2.flgClr-1) and \
            set(node2.category) == set(mainNode.category):
                mainNode.parent.append(node2)
        
    @staticmethod            
    def addDirectSucc(mainNode, node2): 
        if node2.category == ['']:
            cate = []
        else:
            cate = node2.category
        if mainNode.category == ['']:
            cate1 = []
        else:
            cate1 = mainNode.category 
        if mainNode.flgClr == node2.flgClr and len(cate) == len(cate1)-1:
            if Functions.isSublist(mainNode.category, node2.category):
                mainNode.children.append(node2)
        if mainNode.flgClr == node2.flgClr+1:
            if set(node2.category) == set(mainNode.category):
                mainNode.children.append(node2)
                
    @staticmethod 
    def checkDirectPred(mainNode, node2):
        if node2 in mainNode.parent:
            return
        Functions.addDirectPred(mainNode, node2)
#         if node2.category == ['']:
#             cate = []
#         else:
#             cate = node2.category
#         if mainNode.category == ['']:
#             cate1 = []
#         else:
#             cate1 = mainNode.category 
#         if mainNode.flgClr == node2.flgClr and len(cate) == len(cate1)+1:
#             if Functions.isSublist(node2.category, mainNode.category):
#                 mainNode.parent.append(node2)
#         if mainNode.flgClr == node2.flgClr-1:
#             if set(node2.category) == set(mainNode.category):
#                 mainNode.parent.append(node2)
                    
    @staticmethod            
    def checkDirectSucc(mainNode, node2):
        if node2 in mainNode.children:
            return
        Functions.addDirectSucc(mainNode, node2)
#         if node2.category == ['']:
#             cate = []
#         else:
#             cate = node2.category
#         if mainNode.category == ['']:
#             cate1 = []
#         else:
#             cate1 = mainNode.category 
#         if mainNode.flgClr == node2.flgClr and len(cate) == len(cate1)-1:
#             if Functions.isSublist(mainNode.category, node2.category):
#                 mainNode.children.append(node2)
#         if mainNode.flgClr == node2.flgClr+1:
#             if set(node2.category) == set(mainNode.category):
#                 mainNode.children.append(node2)
                            
    @staticmethod
    def generatePredSucc(allnodes, newNodes):
        firstNode, lastNode = None, None
        for n in allnodes:
            for k in allnodes:
                Functions.checkDirectPred(n, k)
                Functions.checkDirectSucc(n, k)
#             for p in n.parent:
#                 print 'parent', n.clearance, n.category, p.clearance, p.category
#             for p in n.children:
#                 print 'children', n.clearance, n.category, p.clearance, p.category
        for n in allnodes:
            if n.parent == []:
                firstNode = n
            elif n.children == []:
                lastNode = n
        return firstNode, lastNode

                
    @staticmethod
    def getClearanceNodeNameFromClrCate(node, clr, cate):
        tempName = '('+clr+',set(['
        for c in cate:
            tempName+="u'"+c+"'"
            if c!=cate[-1]:
                tempName += ','
        tempName += ']))'
        node.name = tempName
        
    @staticmethod    
    def strDirsAssign(names):
        p = re.compile('^((-r|-s|-r -s|-s -r)?\s*(/|(/\w+)+,\s*)*(/|/\w+)+;\s*)*$')
        if re.match(p, names):
            return True
        return False
    
    @staticmethod
    def strNames(names):
        if re.match("[A-Za-z0-9\_]+", names):
            return True
        return False
    
    @staticmethod
    def connectUser2ClrNode(userNames, node): 
        node.relatedUsers = userNames
        node.highlighted = True
        
    @staticmethod 
    def checkExistInfo(main):
        if not main.hasInfo:
            QMessageBox.warning(main, '', 'There is no data', buttons=QMessageBox.Close)
            return
        
    @staticmethod 
    def flag2Option(flag):
        options = ''
        if flag == 0:
            options = ''
        elif flag == 1:
            options = '-s'
        elif flag == 2:
            options = '-r'
        elif flag == 3:
            options = '-r -s'
        return options
    
    @staticmethod
    def getCateStrWithDelimiter(cateList, delimit):
        cateStr = ''
        if cateList != ['']:
            for c in cateList:
                cateStr += "u'"+c+"'"
                if c != cateList[-1]:
                    cateStr+=delimit
        return cateStr
    
    @staticmethod
    def fromCateNum2Name(cateNum, allCate):
        cateList = []
        if cateNum != ['']:
            for i in xrange(len(cateNum)):
                cateList.append(allCate[int(cateNum[i])-1])
            return cateList
        else:
            return cateNum
        
    @staticmethod
    def computeCateNum(node,allCate):
        if node.categoryNumStr=='(':
            i = 1
            cnt = 1
            for n in allCate:
                if n in node.category:
                    node.categoryNumStr += str(i)+','
                    cnt+=1
                i+=1
            if len(node.categoryNumStr)>1:    
                node.categoryNumStr = node.categoryNumStr[:node.categoryNumStr.rfind(',')]
            node.categoryNumStr+=')'
            
    @staticmethod
    def computeCateOrderSum(node, allCate):
        cateOrderSum = 0
        i=1
        for n in allCate:
            if n in node.category:
                cateOrderSum += i
            i+=1
        return cateOrderSum
    