'''
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 Nov 8, 2013

@author: mandy
'''
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Ui_AutogradingSpecDlg import *
import re

class AutogradingSpec(QDialog):

    def __init__(self, scene):
        QDialog.__init__(self)
        self.scene = scene
        self.initParam()
        self.importUi = Ui_importSpec()
        self.importUi.setupUi(self)
#         flags = Qt.Dialog | Qt.WindowStaysOnTopHint
#         self.setWindowFlags(flags)
        self.diagnosisDlg = AutogradingSpecDiagnosis(scene)
        self.importUi.loadinBtn.clicked.connect(self.loadInSpec)
        self.importUi.OKBtn.clicked.connect(self.confimSpec)
        self.importUi.CancelBtn.clicked.connect(self.close)

    def closeEvent(self, evt):
        self.scene.main.ui.actionSpecDiagnosis.setChecked(False)
        evt.accept()
        
    def initParam(self):
        self.specFile = None
        self.specContent = ''
        
    def loadInSpec(self):
        filename = QFileDialog.getOpenFileName(self.scene.main, 'Import MLS Spec', \
                                               directory=self.scene.main.diagramDir, filter='(*.mls);;All Files(*.*)')
        self.specFile = filename
        self.importUi.lineEdit.setText(filename)
        
    def confimSpec(self):
        if self.importUi.lineEdit.text() != '':
            self.close()
            self.importUi.lineEdit.setText('')
            self.diagnosisDlg.show()
            self.diagnosisDlg.checkFormat(self.specFile)
        else:
            QMessageBox.warning(self, '', 'Please input a file name!')
        
class AutogradingSpecDiagnosis(QDialog):
    def __init__(self, scene):
        QDialog.__init__(self)
        self.scene = scene
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        flags = Qt.Dialog | Qt.WindowStaysOnTopHint
        self.setWindowFlags(flags)
        self.ui.closeBtn.clicked.connect(self.close)
        self.ui.clrBtn.clicked.connect(self.clrTextEdit)
        self.ui.loadBtn.clicked.connect(self.loadInSpec)
        
    def loadInSpec(self):
        filename = QFileDialog.getOpenFileName(self, 'Import MLS Spec', directory='./test', filter='(*.mls);;All Files(*.*)')
        self.checkFormat(filename)
        
        
    def closeEvent(self, evt):
        self.clrTextEdit()
        self.scene.main.ui.actionSpecDiagnosis.setChecked(False)
        evt.accept()
        
    def clrTextEdit(self):
        self.ui.textEdit.clear()
        
    def highlightOnelineText(self, text, color, bold):
        text = text.replace('<', '&lt;')
        if bold:
            lText = QString("<b><FONT COLOR="+color+">")#+" FONT SIZE = 3>"
            lText.append(text)
            lText .append("</b></br>")
        else:
            lText = QString("<FONT COLOR="+color+">")#+" FONT SIZE = 3>"
            lText.append(text)
            lText .append("</br>")
        return lText
            
    def getCoreContent(self, l, headDelimiter):
        '''
        delete the comment # part and the header part before :
        '''
        index = l.find('#')
        if index != -1:
            l = l[l.find(headDelimiter)+1:index]
        else:
            l = l[l.find(headDelimiter)+1:]
        return l
    
    def printErrorMessgage(self, text):
        text = self.highlightOnelineText(text, 'red', False)
        self.ui.textEdit.append(text)
        self.ui.textEdit.append('')
            
    def checkClearnaces(self, l):
        lineOK = False
        c = self.getCoreContent(l,':')
        p=re.compile('^ *\w+ *(< *\w+ *)*$')
        if p.match(c) is None:
            l = self.highlightOnelineText(l, 'black', True)
            self.ui.textEdit.append(l)
            text = 'Connect clearances with "&lt;"'
            self.printErrorMessgage(text)
        else:
            self.ui.textEdit.append(l)
            lineOK = True
        return lineOK
            
    def checkCategories(self, l):
        lineOK = False
        c = self.getCoreContent(l,':')
        p=re.compile('^ *\w+ *(, *\w+ *)*$')
        if p.match(c) is None:
            l = self.highlightOnelineText(l, 'black', True)
            self.ui.textEdit.append(l)
            text = 'Connect categories with ","'
            self.printErrorMessgage(text)
        else:
            self.ui.textEdit.append(l)
            lineOK = True
        return lineOK
    
    def checkAssignment(self, l):
        lineOK = False
        c = self.getCoreContent(l, ' ')
        index = c.find('-')
        if index == -1:
            index = c.find('/')
        security = c[:index].replace(' ', '')
        files = c[index:].replace(' ', '')
        #files = files.replace('\t', '')
        #sp = re.compile('^\w+:+\w*$')
        sp = re.compile('^\s*\w+\s*:\s*(\w+\s*:*)*\s*$')
        if sp.match(security) is None:
            '''
            check the security name format
            '''
            l = self.highlightOnelineText(l,'black',True)
            self.ui.textEdit.append(l)
            text = 'Security name should be written as "clearance:category1:category2" or "clearance:"'
            self.printErrorMessgage(text)
        else:
            fp = re.compile('^(-r|-s)*(/\w*)+(,(/\w*))*\t*$')
            if fp.match(files) is None:
                '''
                file directory format is wrong
                '''
                l = self.highlightOnelineText(l,'black',True)
                self.ui.textEdit.append(l)
                text = 'File directories should be written as "-r|-s /path/file, /path2/file2"'
                self.printErrorMessgage(text)
            else:
                self.ui.textEdit.append(l)
                lineOK = True
        return lineOK
    
    def checkUsers(self, l):
        lineOK = False
        c = self.getCoreContent(l, ' ')
        p = re.compile('^\s*(\w+\s*(:\s*\w\s*)*)+\s*(\w+\s*(,\s*\w\s*)*)+$')
        if p.match(c) is None:
            l = self.highlightOnelineText(l,'black',True)
            self.ui.textEdit.append(l)
            text = 'The users assignment should be written as "users clearance:category1:category2 user1, user2" or "users clearance: user1"'
            self.printErrorMessgage(text)
        else:
            self.ui.textEdit.append(l) 
            lineOK = True
        return lineOK
    
    def checkFormat(self, filename):
        f = open(filename, 'r')
        lines = f.readlines()
        self.ui.textEdit.setReadOnly(True)
        self.specContent = ''.join(lines)
        numClr = 0
        numCate = 0
        specOK = True
        
        #if self.ui.textEdit.text()!= '':
        specName = str(filename)
        specName = specName[specName.rfind('/')+1:]
        separator = '-'*30+specName+'-'*30
        separator = self.highlightOnelineText(separator,'blue',True)
        self.ui.textEdit.append('')
        self.ui.textEdit.append(separator)
        self.ui.textEdit.append('')
        
        for l in lines:
            text = l.strip('\n')
            index = l.find('#')
            if index != -1:
                l = l[:index]
            if l.find('clearances:')!=-1:
                numClr += 1
                if self.checkClearnaces(text) == False:
                    specOK = False
            elif l.find('categories:')!=-1:
                numCate+=1
                if self.checkCategories(text) == False:
                    specOK = False
            elif l.find('assign')!= -1:
                if self.checkAssignment(text) == False:
                    specOK = False
            elif l.find('users')!=-1:
                if self.checkUsers(text) == False:
                    specOK = False
            else:
                self.ui.textEdit.append(text)
        if numClr == 0:
            text = 'Clearances in the system should be included.'
            text = self.highlightOnelineText(text, 'red', False)
            self.ui.textEdit.append(text)
            text = 'The format is "clearances:clearance1&lt;clearance2"'
            specOK = False
#            text = self.highlightOnelineText(text, 'red', False)
#            self.ui.textEdit.append(text)
#            self.ui.textEdit.append('\n')
            self.printErrorMessgage(text)
        if numCate == 0:
            text = 'Categories in the system should be included.'
            text = self.highlightOnelineText(text,'red', False)
            self.ui.textEdit.append(text)
            text = 'The format is "categories:category1,category2"'
#            text = self.highlightOnelineText(text,'red', False)
#            self.ui.textEdit.append(text)
#            self.ui.textEdit.append('\n')
            self.printErrorMessgage(text)
            specOK = False
        f.close()
        if specOK and numClr == 1 and numCate == 1:
            self.ui.textEdit.append('')
            text = self.highlightOnelineText('The specification is correct!', 'green', True)
            self.ui.textEdit.append(text)

        
            