'''
Created on Sep 10, 2014

@author: Mandy
'''
from PyQt4 import QtCore, QtGui
import re

# try:
#     _fromUtf8 = QtCore.QString.fromUtf8
# except AttributeError:
#     _fromUtf8 = lambda s: s
        
class ToolBoxContextHandler(QtGui.QWidget):
    
    def __init__(self, main, parent = None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        self.main = main
        self.flag = -1
        vbox = QtGui.QVBoxLayout(self)
        self.label = QtGui.QLabel()
        self.lineEdit = QtGui.QLineEdit()
        self.comboBox = QtGui.QComboBox()
        self.OKButton = QtGui.QPushButton('OK')
        self.cancelButton = QtGui.QPushButton('Cancel')
        self.permsGroupBox = QtGui.QGroupBox('Permissions')
        permsVLayout = QtGui.QVBoxLayout()
        self.modifyPermsCBox_recursive = QtGui.QCheckBox('Recursive')
        self.modifyPermsCBox_read = QtGui.QCheckBox('Read')
        self.modifyPermsCBox_write = QtGui.QCheckBox('Write')
        self.modifyPermsCBox_exe = QtGui.QCheckBox('Execute')
        permsVLayout.addWidget(self.modifyPermsCBox_recursive)
        permsVLayout.addWidget(self.modifyPermsCBox_read)
        permsVLayout.addWidget(self.modifyPermsCBox_write)
        permsVLayout.addWidget(self.modifyPermsCBox_exe)
        self.permsGroupBox.setLayout(permsVLayout)
        vbox.addWidget(self.label)
        vbox.addWidget(self.lineEdit)
        vbox.addWidget(self.comboBox)
        vbox.addWidget(self.permsGroupBox)
        buttonPairWidget = QtGui.QWidget()
        self.buttonPairLayout = QtGui.QHBoxLayout()
        self.buttonPairLayout.addWidget(self.OKButton)
        self.buttonPairLayout.addWidget(self.cancelButton)
        buttonPairWidget.setLayout(self.buttonPairLayout)
        vbox.addWidget(buttonPairWidget)
        self.setLayout(vbox)
        self.lineEdit.setVisible(False)
        self.comboBox.setVisible(True)
        self.permsGroupBox.setVisible(True)
        self.cancelButton.clicked.connect(self.closeWindow)
        self.OKButton.clicked.connect(self.confirmEdit)

    def resetAllWidgets(self):
        self.setLabelContent('')
        self.clearLineEdit()
        
    def setPermsCheckBoxStates(self, recurstate, rstate, wstate, xstate):
        self.modifyPermsCBox_recursive.setChecked(recurstate)
        self.modifyPermsCBox_read.setChecked(rstate)
        self.modifyPermsCBox_write.setChecked(wstate)
        self.modifyPermsCBox_exe.setChecked(xstate)
    
    def getPermsFromCheckBoxes(self):
        permset = set()
        recursive = False
        if self.modifyPermsCBox_recursive.isChecked():
            recursive = True
        if self.modifyPermsCBox_read.isChecked():
            permset.add('r')
        if self.modifyPermsCBox_write.isChecked():
            permset.add('w')
        if self.modifyPermsCBox_exe.isChecked():
            permset.add('x')
        return recursive, permset
        
    def setCheckBoxesFromPermset(self, recursive, permset):
        self.modifyPermsCBox_recursive.setChecked(recursive)
        if 'r' in permset:
            self.modifyPermsCBox_read.setChecked(True)
        else:
            self.modifyPermsCBox_read.setChecked(False)
        if 'w' in permset:
            self.modifyPermsCBox_write.setChecked(True)
        else:
            self.modifyPermsCBox_write.setChecked(False)
        if 'x' in permset:
            self.modifyPermsCBox_exe.setChecked(True)
        else:
            self.modifyPermsCBox_exe.setChecked(False)
        
    def setLabelContent(self, text):
        self.label.setText(text)

    def clearLineEdit(self):
        self.lineEdit.clear()

    def closeWindow(self):
        self.resetAllWidgets()
        self.close()
        
    def closeEvent(self, evt):
        self.resetAllWidgets()
        evt.accept()
        
    def isNameEmpty(self, name):
        p = re.compile('^(\s)*$')
        if p.match(name):
            return True
        else:
            return False
        
    def addItemsToComboBox(self, itemlist, comboBox):
        for i in itemlist:
            comboBox.addItem(i)
            
    def setComboBoxContentForRoleAddParent(self, rolenode):
        '''for add parent nodes'''
        self.comboBox.clear()
        negRoleParentNodeSet = self.main.roleSet-rolenode.parents
        negRoleParentNodeSet.remove(rolenode.name)
        self.addItemsToComboBox(negRoleParentNodeSet, self.comboBox)
         
    def setComboBoxContentForRoleDeleteParent(self, rolenode):
        '''for delete parent nodes'''
        self.comboBox.clear()
        self.addItemsToComboBox(rolenode.parents, self.comboBox)
               
    def setComboBoxContentForRoleAddChild(self, rolenode):
        self.comboBox.clear()
        '''for add children nodes'''
        negRoleChildrenNodeSet = self.main.roleSet-rolenode.children
        negRoleChildrenNodeSet.remove(rolenode.name)
        self.addItemsToComboBox(negRoleChildrenNodeSet, self.comboBox)
        
    def setComboBoxContentForRoleDeleteChild(self, rolenode):
        self.comboBox.clear()
        '''for delete children nodes'''
        self.addItemsToComboBox(rolenode.children, self.comboBox)

    def setComboBoxRoleAddUser(self, rolenode):
        self.comboBox.clear()
        '''for add user nodes'''
        userSet = set()
        for u in rolenode.userNodes:
            userSet.add(u.name)
        negUserSet = self.main.userSet-userSet
        self.addItemsToComboBox(negUserSet, self.comboBox)
                
    def setComboBoxRoleDeleteUser(self, rolenode):
        self.comboBox.clear()
        '''for delete user nodes'''
        userSet = set()
        for u in rolenode.userNodes:
            userSet.add(u.name)
        self.addItemsToComboBox(userSet, self.comboBox)

    def setComboBoxRoleAddDir(self, rolenode):
        self.comboBox.clear()
        '''for add dir nodes'''
        dirSet = set()
        for d in rolenode.dirNodes:
            dirSet.add(d.dir)
        negDirSet = self.main.dirSet-dirSet
        self.addItemsToComboBox(negDirSet, self.comboBox)
        
    def setComboBoxRoleDeleteDir(self, rolenode):
        self.comboBox.clear()
        '''for delete dir nodes'''
        dirSet = set()
        for d in rolenode.dirNodes:
            dirSet.add(d.dir)
        self.addItemsToComboBox(dirSet, self.comboBox)
        
    '''for user nodes'''
    def setComboBoxUserAddRole(self, usernode):
        self.comboBox.clear()
        userRoleNodeSet = self.main.user_role_mat[usernode.name]
        negUserRoleNodeSet = self.main.roleSet-userRoleNodeSet
        self.addItemsToComboBox(negUserRoleNodeSet, self.comboBox)
        
    def setComboBoxUserDeleteRole(self, usernode):
        self.comboBox.clear()
        userRoleNodeSet = self.main.user_role_mat[usernode.name]
        self.addItemsToComboBox(userRoleNodeSet, self.comboBox)
        
    '''for dir nodes'''
    def setComboBoxDirAddRole(self, dirnode):
        self.comboBox.clear()
        dirRoleNodeSet = set()
        for r in dirnode.roleNodes:
            dirRoleNodeSet.add(r.name)
        negDirRoleNodeSet = self.main.roleSet-dirRoleNodeSet
        self.addItemsToComboBox(negDirRoleNodeSet, self.comboBox)
        self.setPermsCheckBoxStates(False, False, False, False)

    def setComboBoxDirDeleteRole(self, dirnode):
        self.comboBox.clear()
        dirRoleNodeSet = set()
        for r in dirnode.roleNodes:
            dirRoleNodeSet.add(r.name)
        self.addItemsToComboBox(dirRoleNodeSet, self.comboBox)
        index = self.comboBox.currentIndex()
        self.getContentForPermsComboBox0(index)
            
    def getContentForPermsComboBox0(self, textIndex):
        itemname = str(self.comboBox.itemText(textIndex))
        if self.item.dir not in self.main.role_res_mat[itemname].keys():
            return
        permSet = self.main.role_res_mat[itemname][self.item.dir]
        self.setCheckBoxesFromPermset(permSet.recursive, permSet.perms)
         
    def modifyPolicy(self, nodeToChange, flag):
        self.resetAllWidgets()
        self.flag = flag
        self.item = nodeToChange
        if flag == self.main.scene.ADD_PARENT_ROLE:
            self.setLabelContent('Select a role as parent:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxContentForRoleAddParent(nodeToChange)
        elif flag == self.main.scene.DELETE_PARENT_ROLE:
            self.setLabelContent('Select a role to remove from parents:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxContentForRoleDeleteParent(nodeToChange)
        elif flag == self.main.scene.ADD_CHILD_ROLE:
            self.setLabelContent('Select a role as child:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxContentForRoleAddChild(nodeToChange)
        elif flag == self.main.scene.DELETE_CHILD_ROLE:
            self.setLabelContent('Select a role to remove from children:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxContentForRoleDeleteChild(nodeToChange)
        elif flag == self.main.scene.ADD_USER_2ROLE:
            self.setLabelContent('Select a user to attach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxRoleAddUser(nodeToChange)
        elif flag == self.main.scene.DELETE_USER_2ROLE:
            self.setLabelContent('Select an user to detach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxRoleDeleteUser(nodeToChange)
        elif flag == self.main.scene.ADD_DIR_2ROLE:
            self.setLabelContent('Select an object to attach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(True)
            self.setComboBoxRoleAddDir(nodeToChange)
        elif flag == self.main.scene.DELETE_DIR_2ROLE:
            self.setLabelContent('Select an object to detach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(True)
            self.setComboBoxRoleDeleteDir(nodeToChange)
        elif flag == self.main.scene.ADD_ROLE_2USER:
            self.setLabelContent('Select a role to attach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxUserAddRole(nodeToChange)
        elif flag == self.main.scene.DELETE_ROLE_2USER:
            self.setLabelContent('Select a role to detach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(False)
            self.setComboBoxUserDeleteRole(nodeToChange)
        elif flag == self.main.scene.ADD_ROLE_2DIR:
            self.setLabelContent('Select a role to attach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(True)
            self.setComboBoxDirAddRole(nodeToChange)
        elif flag == self.main.scene.DELETE_ROLE_2DIR:
            self.setLabelContent('Select a role to detach:')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(True)
            self.permsGroupBox.setVisible(True)
            self.setComboBoxDirDeleteRole(nodeToChange)
        elif flag == self.main.scene.CREATE_ROLENODE:
            self.setLabelContent('Enter a new role:')   
            self.lineEdit.setVisible(True)
            self.comboBox.setVisible(False)  
            self.permsGroupBox.setVisible(False)   
        elif flag == self.main.scene.DELETE_ROLENODE:
            self.setLabelContent('Are you sure to delete this role?')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(False)
            self.permsGroupBox.setVisible(False)
        elif flag == self.main.scene.CREATE_USERNODE:
            self.setLabelContent('Enter a new user:')
            self.lineEdit.setVisible(True)
            self.comboBox.setVisible(False)
            self.permsGroupBox.setVisible(False)
        elif flag == self.main.scene.DELETE_USERNODE:
            self.setLabelContent('Are you sure to delete this user?')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(False)
            self.permsGroupBox.setVisible(False)
        elif flag == self.main.scene.CREATE_DIRNODE:
            self.setLabelContent('Enter a new object:')
            self.lineEdit.setVisible(True)
            self.comboBox.setVisible(False)
            self.permsGroupBox.setVisible(False)
        elif flag == self.main.scene.DELETE_DIRNODE:
            self.setLabelContent('Are you sure to delete this object?')
            self.lineEdit.setVisible(False)
            self.comboBox.setVisible(False)
            self.permsGroupBox.setVisible(False)
        self.show()
        
    def lineEditInputEmptyWarning(self):
        warningText = 'Please input a '
        if self.flag == self.main.scene.CREATE_ROLENODE:
            warningText += 'role name!'
        elif self.flag == self.main.scene.CREATE_DIRNODE:
            warningText += 'directory name!'
        elif self.flag == self.main.scene.CREATE_USERNODE:
            warningText += 'user name!'
        QtGui.QMessageBox.critical(self, 'Error', warningText)
        
    def confirmEdit(self):
        text = str(self.comboBox.currentText())
        if self.flag == self.main.scene.ADD_PARENT_ROLE:
            self.closeWindow()
            self.main.policyManager.addParent_modifyRoleInPolicy(self.item.name, text)
            message = "Role("+self.item.name+"): Add: Parent("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_PARENT_ROLE:
            self.closeWindow()
            self.main.policyManager.deleteParent_modifyRoleInPolicy(self.item.name, text)
            message = "Role("+self.item.name+"): Delete: Parent("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.ADD_CHILD_ROLE:
            self.closeWindow()
            self.main.policyManager.addChild_modifyRoleInPolicy(self.item.name, text)
            message = "Role("+self.item.name+"): Add: Child("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_CHILD_ROLE:
            self.closeWindow()
            self.main.policyManager.deleteChild_modifyRoleInPolicy(self.item.name, text)
            message = "Role("+self.item.name+"): Delete: Child("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.ADD_USER_2ROLE:
            self.closeWindow()
            self.main.policyManager.addRole_modifyUserInPolicy(text, self.item.name)
            message = "Role("+self.item.name+"): Add: User("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_USER_2ROLE:
            self.closeWindow()
            self.main.policyManager.deleteRole_modifyUserInPolicy(text, self.item.name)
            message = "Role("+self.item.name+"): Delete: User("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.ADD_DIR_2ROLE:
            recursive, permset = self.getPermsFromCheckBoxes()
            if permset==set():
                QtGui.QMessageBox.warning(self, 'Warning', 'No permission information has been entered! No change applied!')
            else:
                self.closeWindow()
                self.main.policyManager.addRole_modifyDirInPolicy(text, self.item.name, recursive, permset)
                if recursive:
                    r = '-r'
                else:
                    r = ''
                message = "Role("+self.item.name+"): Add: Object("+text+"): Perms("+r+"|"+','.join(permset)+")\n"
                self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_DIR_2ROLE:
            recursive, permset = self.getPermsFromCheckBoxes()
            self.closeWindow()
            self.main.policyManager.deleteRole_modifyDirInPolicy(text, self.item.name, recursive, permset)
            if recursive:
                r = '-r'
            else:
                r = ''
            message = "Role("+self.item.name+"): Delete: Object("+text+"): Perms("+r+"|"+','.join(permset)+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.ADD_ROLE_2USER:
            self.closeWindow()
            self.main.policyManager.addRole_modifyUserInPolicy(self.item.name, text)
            message = "User("+self.item.name+"): Add: Role("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_ROLE_2USER:
            self.closeWindow()
            self.main.policyManager.deleteRole_modifyUserInPolicy(self.item.name, text)
            message = "User("+self.item.name+"): Delete: Role("+text+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.ADD_ROLE_2DIR:
            recursive, permset = self.getPermsFromCheckBoxes()
            if permset==set():
                QtGui.QMessageBox.warning(self, 'Warning', 'No permission information has been entered! No change applied!')
            else:
                self.closeWindow()
                self.main.policyManager.addRole_modifyDirInPolicy(self.item.dir, text, recursive, permset)
                if recursive:
                    r = '-r'
                else:
                    r = ''
                message = "Object("+self.item.dir+"): Add: Role("+text+"): Perms("+r+"|"+','.join(permset)+")\n"
                self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_ROLE_2DIR:
            recursive, permset = self.getPermsFromCheckBoxes()
            self.closeWindow()
            self.main.policyManager.deleteRole_modifyDirInPolicy(self.item.dir, text, recursive, permset)
            if recursive:
                r = '-r'
            else:
                r = ''
            message = "Object("+self.item.dir+"): Delete: Role("+text+"): Perms("+r+"|"+','.join(permset)+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.CREATE_ROLENODE:
            lineEditText = str(self.lineEdit.text())
            if self.isNameEmpty(lineEditText):
                self.lineEditInputEmptyWarning()
            else:
                self.closeWindow()
                self.main.policyManager.addRoleToPolicy(lineEditText)
                message = "Role("+lineEditText+"): Create\n"
                self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_ROLENODE:
            self.closeWindow()
            self.main.policyManager.deleteRoleInPolicy(self.item.name)
            message = "Role("+self.item.name+"): Delete\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.CREATE_USERNODE:
            lineEditText = str(self.lineEdit.text())
            if self.isNameEmpty(lineEditText):
                self.lineEditInputEmptyWarning()
            else:
                self.closeWindow()
                self.main.policyManager.addUserToPolicy(lineEditText)
                message = "User("+lineEditText+"): Create\n"
                self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_USERNODE:
            self.closeWindow()
            self.main.policyManager.deleteUserInPolicy(self.item.name)
            message = "User("+self.item.name+"): Delete\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.CREATE_DIRNODE:
            lineEditText = str(self.lineEdit.text())
            if self.isNameEmpty(lineEditText):
                self.lineEditInputEmptyWarning()
            else:
                self.closeWindow()
                self.main.policyManager.addDirToPolicy(lineEditText)
                message = "Object("+lineEditText+"): Create\n"
                self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        elif self.flag == self.main.scene.DELETE_DIRNODE:
            self.closeWindow()
            self.main.policyManager.deleteDirInPolicy(self.item.dir)
            message = "Object("+self.item.dir+"): Delete\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        self.main.specDialog.getSpecFromVisualization()