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

@author: yifli
'''
from PyQt4.QtGui import QDialog
from Ui_SpecDialog import Ui_Dialog
from TypeNode import TypeNode
from DomainNode import DomainNode
from FileNode import FileNode
from EdgeItem import EdgeItem

class SpecDialog(QDialog):
    def __init__(self, scene):
        QDialog.__init__(self)
        self.scene = scene
        
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.setLayout(self.ui.verticalLayout)
        self.ui.errorLabel.setWordWrap(True)
        
        self.ui.generatePushButton.clicked.connect(self.reGenerateSpec)
        self.ui.closePushButton.clicked.connect(self.close)

    def closeEvent(self, evt):
        self.scene.main.writeToFile(self.scene.main.logFile, self.scene.main.getCurrentTimeString()+\
                                    "Specification Dialog turned off\n")
        evt.accept()
        
    def reGenerateSpec(self):
        
        typeNodes = []
        domainNodes = []
        assignMap = {}
        initialDomain = None
        errorMsg = ''
        spec = ''

        for item in self.scene.items():
            if isinstance(item, TypeNode):
                typeNodes.append(item)
            elif isinstance(item, DomainNode):
                domainNodes.append(item)
                if item.initialDomain:
                    initialDomain = item
            elif isinstance(item, FileNode):
                if item.type is not None:
                    if item.inheritFromNode is None:
                        #print 'sepc', item.type.name, item.name, item.fullPath
                        if item.type in assignMap:
                            if item.flag == 0:
                                assignMap[item.type][''].append(item)
                            elif item.flag == 1:
                                assignMap[item.type]['-s'].append(item)
                            elif item.flag == 2:
                                assignMap[item.type]['-r'].append(item)
                            else:
                                assignMap[item.type]['-r -s'].append(item)
                        else:
                            assignMap[item.type] = {}
                            assignMap[item.type][''] = []
                            assignMap[item.type]['-s'] = []
                            assignMap[item.type]['-r'] = []
                            assignMap[item.type]['-r -s'] = []
                            if item.flag == 0:
                                assignMap[item.type][''].append(item)
                            elif item.flag == 1:
                                assignMap[item.type]['-s'].append(item)
                            elif item.flag == 2:
                                assignMap[item.type]['-r'].append(item)
                            else:
                                assignMap[item.type]['-r -s'].append(item)
        
        if not domainNodes:
            errorMsg += 'No domains are defined.\n'
        if not typeNodes:
            errorMsg += 'No types are defined. \n'
                                                          
        if initialDomain is None:
            errorMsg += 'No initial domain is set. \n'
        
        if typeNodes:
            spec += 'type %s;\n' % ','.join([str(t.name) for t in typeNodes])
        
        for d in domainNodes:
            typeMap = {}
            transitionMap = {}
            transitionMap['auto'] =[]
            transitionMap['exec'] = []
            triggers = []
            if d.initialDomain:
                triggers.append(d.entryPoints)
                
            for e in d.edgeList:
                if e.startItem is d:
                    if e.type == EdgeItem.TYPE_CONN:
                        canonicalDescription = ''.join(sorted(str(e.description)))
                        if canonicalDescription in typeMap:
                            typeMap[canonicalDescription].append(str(e.endItem.name))
                        else:
                            typeMap[canonicalDescription] = [str(e.endItem.name)]
                    elif e.type == EdgeItem.AUTO_CONN:
                        transitionMap['auto'].append(str(e.endItem.name))
                    elif e.type == EdgeItem.EXEC_CONN:
                        transitionMap['exec'].append(str(e.endItem.name))
                elif e.endItem is d:
                    if e.type == EdgeItem.AUTO_CONN or e.type == EdgeItem.EXEC_CONN:
                        triggers.append(str(e.description))
            
            if not triggers:
                errorMsg += 'No entry point program is found for domain %s.\n' % (str(d.name))
            entryPoints = ','.join([str(t) for t in triggers])
            
            permissions = ''
            if typeMap:
                for k, v in typeMap.items():
                    permissions += '        (%s->%s),\n' %  (k, ','.join([str(t) for t in v]))
            
            if transitionMap['auto'] and transitionMap['exec']:
                spec += 'domain %s = (%s),\n' % (str(d.name), entryPoints)
                if permissions != '':
                    spec += permissions
                spec += '        (auto->%s),\n' % ','.join([str(t) for t in transitionMap['auto']])
                spec += '        (exec->%s);\n' % ','.join([str(t) for t in transitionMap['exec']])
            else:
                if transitionMap['auto']:
                    spec += 'domain %s = (%s),\n' % (str(d.name), entryPoints)
                    if permissions != '':
                        spec += permissions
                    spec += '        (auto->%s);\n' % ','.join([str(t) for t in transitionMap['auto']])
                elif transitionMap['exec']:
                    spec += 'domain %s = (%s),\n' % (str(d.name), entryPoints)
                    if permissions != '':
                        spec += permissions
                    spec += '        (exec->%s);\n' % ','.join([str(t) for t in transitionMap['exec']])
                else:
                    if permissions != '':
                        spec += 'domain %s = (%s),\n' % (str(d.name), entryPoints)
                        permissions = permissions[0:-2] + ';\n'
                        spec += permissions
                    else:
                        spec += 'domain %s = (%s);\n' % (str(d.name), entryPoints)
 
        if initialDomain is not None:        
            spec += 'initial_domain = %s;\n' % str(initialDomain.name)
        
        if len(assignMap) > 0 :
            for k, v in assignMap.items():
                for kk, vv in v.items():
                    if vv:
                        spec += 'assign %s %s %s;\n' % (kk, str(k.name), ','.join([str(t.fullPath) for t in vv]))
        else:
            errorMsg += 'No type is assigned to any file/directory.'
            
        self.ui.specTextEdit.clear()
        self.ui.specTextEdit.setPlainText(spec)
        
        if errorMsg == '':
            self.ui.errorLabel.setText('Error: None')
            self.ui.errorLabel.adjustSize()
        else:
            self.ui.errorLabel.setText(errorMsg)
            self.ui.errorLabel.adjustSize()

        
        
    
