'''
Created on Nov 30, 2014

@author: manwang
'''
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from AccessControlMain import AccessControlMain
from commonFunction import Functions
from MainWindow import MainWindow
import re
    
class MLSForCommandLine(object):

    def __init__(self):
        self.app = None
        if self.app is None:
            self.app= self.startVisualizationWindow()
#         self.importPolicy('/Users/manwang/Documents/workspace/MLSvisual/src/policies/mlsspec.mls')
#         self.initVisualizationForQuery(QString('/Users/manwang/Documents/workspace/MLSvisual/src/policies/mlsspec.mls'), 1)
        
    def UIConfiForQuery(self, questionId, paras):
        #self.main.initParam()
        self.main.queryWindowDockWidget.show()
        self.main.queryWindow.setQueryForQuestion(questionId)
        self.main.queryWindow.getQueryResultFromCommandLineInput(questionId, paras)
        self.main.currentAction = self.main.ui.actionGeneral_Graph
        self.main.viewModeChanged(self.main.currentAction)
        
    def startVisualizationWindow(self):
        app = QApplication(sys.argv)
        QCoreApplication.setApplicationName('MLSvisual')
        QCoreApplication.setApplicationVersion('1.0')
        
        QApplication.setStyle('plastique')
        app.setStyleSheet("""QToolTip {
                            background-color:white;
                            color:black;
        }""")
        self.main = MainWindow()
        return app
    
    def initVisualizationForQuery(self, filename, questionId, paras=[]):
        #paras is a list containing the input for query interface
        self.main.show()
        self.main.importSpecFile(filename)#need changes to avoid repeated reloads
        self.UIConfiForQuery(questionId, paras)
        exitcode = self.app.exec_()
        sys.exit(exitcode)
        self.app = None
        
#     def initInterface(self):
#         self.wholeGraphDialog.wholeGraphScene.resetAll()
#         self.view.setDragMode(QGraphicsView.NoDrag)
#         self.ui.actionGeneral_Graph.setChecked(True)
#         self.viewModeChanged(self.ui.actionGeneral_Graph)
#         self.setWindowTitle('MLSvisual')
#         
#     def initParam(self):
#         self.scene.initParam()
#         self.ioHelper.initParam()
#         self.hasInfo = False
#         self.computeTypeGraph = 0
#         self.longestBtnWidth = 50
#         self.hasClr, self.hasCate = False, False
#         self.savedMLSVisName = None
#         self.initInterface()

    def importPolicy(self, filename):
        if filename != '':
            self.main.initParam()
            self.main.hasInfo = True
            self.main.specFileDir = filename
            try:
                AccessControlMain(str(filename), './parsedfile.txt')
#                 source = '''
#                 clearances: clr1 > clr2 > clr4
#                 # whole line comment
#                 clearances: clr2 > clr5         # foo
#                 clearances: clr1 > clr3 > clr5
#                 categories: cat1, cat2            # bar buzz 
#                 
#                 assign: clr1:cat1 -r /usr        # a comment
#                 assign: clr3:cat2 /usr/somefile
#                 
#                 users: clr2:cat1,cat2 user1,user2
#                 users: clr3:cat1 user3,user4
#                 '''
#                 (self.clearance_lattice,
#                  self.categories,
#                  self.resource_dict,
#                  self.user_dict) = mlspolicy(str(filename))
#                 print self.clearance_lattice
#                 print
#                 print self.categories
#                 print
#                 print self.resource_dict
#                 print 
#                 print self.user_dict
                self.main.ioHelper.import_(filename, './parsedfile.txt')
#                 self.getTypeUserNodes(filename)
#                 self.getLatticeNode('./parsedfile.txt')
#                 self.addTypeNode2Scene()
#                 self.add2Scene.getEdgeItem()
#                 self.add2Scene.getFileNodes()
#                 self.scene.categoryCombination = Functions.allCateCombination(self.scene.categories)
            except Exception as e:
                return
            securitylevel1 = Functions.makeSecurityLevel('secret', set(['michigan', 'texas']))
            securitylevel2 = Functions.makeSecurityLevel('seven', set(['texas']))
            securitylevel3 = Functions.makeSecurityLevel('secret', set(['']))
            self.queryManager('none', securitylevel3, '/usr', set(['r', 'w']))
            self.queryManager('ricky', 'none', '/usr', set(['r']))
#             self.queryManager('fred',securitylevel1, '/top', set())
#             self.queryManager('lucy',securitylevel2, '/usr/somefile', set())
    
    def queryManager(self, username, securitylevel, objname, permset):
        noneinput = re.compile('none', re.IGNORECASE)
        if re.match(noneinput, username):
            self.querySLAccessObj(securitylevel, objname, permset)
        elif re.match(noneinput, securitylevel):#re.match(noneinput, Functions.securityLevelName(securitylevel)):
            self.queryUserAccessObj(username, objname, permset)
        else:
            self.queryUserAccessObjFromSL(username, securitylevel, objname, permset)
            
    def permAnswer(self, readable, writable, permset, output):
        if permset == set(['']) or permset == set():
            answer = False
            output='Please specify the permissions to object '
        else:
            if permset==set(['r']):
                if readable:
                    answer = True
                    output+= 'can read object '
                else:
                    answer = False
                    output+='cannot read object '
            elif permset==set(['w']):
                if writable:
                    answer = True
                    output+='can write object '
                else:
                    answer = True
                    output+= 'cannot write object '
            elif permset==set(['r', 'w']):
                if readable and writable:
                    answer = True
                    output+= 'can read and write object '
                elif readable:
                    answer = False
                    output+= 'can read but cannot write object '
                elif writable:
                    answer = False
                    output+= 'can write but cannot read object '
                else:
                    answer = False
                    output+= 'can neither read nor write object '
        return answer, output
                
    def querySLAccessObj(self, securitylevel, objname, permset):
        name = Functions.securityLevelName(securitylevel)
        output = 'Subjects at security level "'+name+'" '
        oClr, oFlgClr, oCateSet = self.main.queryWindow.getClrcateOfObj(objname)
        SLFlgClr = self.main.queryWindow.getClrFlg(securitylevel.clearance)
        readable = self.main.queryWindow.canReadSL(SLFlgClr, securitylevel.categoryset, oFlgClr, oCateSet)
        writable = self.main.queryWindow.canWriteSL(SLFlgClr, securitylevel.categoryset, oFlgClr, oCateSet)
        answer, output = self.permAnswer(readable, writable, permset, output)
        output+='"'+objname+'"'
        return answer, output
    
    def queryUserAccessObj(self, username, objname, permset):
        uClr, uFlgClr, uCateSet = self.main.queryWindow.getClrcateOfUser(username)
        oClr, oFlgClr, oCateSet = self.main.queryWindow.getClrcateOfObj(objname)
        readable = self.main.queryWindow.canReadSL(uFlgClr, uCateSet, oFlgClr, oCateSet)
        writable = self.main.queryWindow.canWriteSL(uFlgClr, uCateSet, oFlgClr, oCateSet)
        output = 'User "'+username+'" '
        answer, output = self.permAnswer(readable, writable, permset, output)
        output+='"'+objname+'"'
        return answer, output
    
    def queryUserAccessObjFromSL(self, username, securitylevel, objname, permset):
        output = 'User "'+username+'" '
        uClr, uFlgClr, uCateSet = self.main.queryWindow.getClrcateOfUser(username)
        if securitylevel.clearance != uClr or securitylevel.categoryset != uCateSet:
            answer = False
            output += 'is not assigned to security level "'+Functions.securityLevelName(securitylevel)+'". Therefore, the user cannot '+\
            'access object "'+objname+'" through this security level'
        else:
            output += 'is assigend to security level "'+Functions.securityLevelName(securitylevel)+\
            '" and '
            oClr, oFlgClr, oCateSet = self.main.queryWindow.getClrcateOfObj(objname)
            readable = self.main.queryWindow.canReadSL(uFlgClr, uCateSet, oFlgClr, oCateSet)
            writable = self.main.queryWindow.canWriteSL(uFlgClr, uCateSet, oFlgClr, oCateSet)
            answer, output = self.permAnswer(readable, writable, permset, output)
            output+='"'+objname+'"'
#             if readable and writable:
#                 answer = True
#                 output+= 'can read and write object "'+objname+'"'
#             elif readable:
#                 answer = True
#                 output+= 'can read object "'+objname+'"'
#             elif writable:
#                 answer = True
#                 output+= 'can write object "'+objname+'"'
#             else:
#                 answer = False
#                 output+= 'can neither read nor write object "'+objname+'"'
        return answer, output