'''
Created on Oct 19, 2014

@author: mandy
'''

# from Crypto.PublicKey import RSA
# from base64 import b64decode
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Ui_AnswerFileLoad import Ui_AnswerFileLoad
from Ui_EncodedAnswerRenameDlg import Ui_EncodedAnswerRenameDlg
import os, math, subprocess, sys

class EncodedAnswerRenameDlg(QDialog):
    def __init__(self, main):
        QDialog.__init__(self)
        self.ui = Ui_EncodedAnswerRenameDlg()
        self.ui.setupUi(self)
        self.main = main
        self.ui.lineEdit.setVisible(True)
        self.ui.pushButton_OK.setText('OK')
        self.ui.pushButton_Cancel.setText('Cancel')
        self.ui.pushButton_Cancel.clicked.connect(self.closeWindow)
        self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint)
        
    def closeWindow(self):
        self.ui.lineEdit.clear()
        self.close()
        
    def closeEvent(self, evt):
        self.ui.lineEdit.clear()
        evt.accept()
        
class EncodedAnswerRenameWarningDlg(QDialog):
    def __init__(self, main):
        QDialog.__init__(self)
        self.ui = Ui_EncodedAnswerRenameDlg()
        self.ui.setupUi(self)
        self.ui.lineEdit.setVisible(False)
        self.ui.pushButton_OK.setText('Yes')
        self.ui.pushButton_Cancel.setText('No')
        self.main = main
        
    def closeWindow(self):
        self.close()
        
    def closeEvent(self, evt):
        evt.accept()
        
class EmailInstructorDlg(QDialog):
    def __init__(self, main):
        QDialog.__init__(self)
        self.ui = Ui_EncodedAnswerRenameDlg()
        self.ui.setupUi(self)
        self.main = main
        self.ui.lineEdit.setVisible(True)
        self.ui.pushButton_OK.setText('OK')
        self.ui.pushButton_Cancel.setText('Close')
        self.ui.label.setText("Please enter instructor's email address:")
        self.ui.pushButton_Cancel.clicked.connect(self.closeWindow)
        self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint)
        
    def closeWindow(self):
        reply = QMessageBox.warning(self, '', 'Are you sure to exit the submission process?\
                                    \n Confirm this action will lose your answers!', QMessageBox.Yes|QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.ui.lineEdit.clear()
            self.close()
        
    def closeEvent(self, evt):
        self.ui.lineEdit.clear()
        evt.accept()
        
class AnswerFileLoadDlg(QDialog):
    def __init__(self, main):
        QDialog.__init__(self)
        self.ui = Ui_AnswerFileLoad()
        self.ui.setupUi(self)
        self.main = main
        self.ui.pushButton_Cancel.clicked.connect(self.closeWindow)
        
    def closeWindow(self):
        self.ui.lineEdit_Dir.clear()
        self.main.ui.actionDecrypt.setChecked(False)
        self.close()
        self.main.ui.introLabel.setText('')
        
    def closeEvent(self, evt):
        self.ui.lineEdit_Dir.clear()
        self.main.ui.actionDecrypt.setChecked(False)
        evt.accept()
        self.main.ui.introLabel.setText('')
        
class AnswerDecryption(object):

    def __init__(self, main):
        '''Constructor'''
        self.main = main
        self.answerFileLoadDlg = AnswerFileLoadDlg(main)
        self.encodedAnswerRenameDlg = EncodedAnswerRenameDlg(main)
        self.renameWarningDlg = EncodedAnswerRenameWarningDlg(main)
        self.emailInstructorDlg = EmailInstructorDlg(main)
        self.privateKey, self.publicKey = None, None
        #self.privateKey, self.publicKey = self.generateKeyPairs(1024)
        self.answerFileLoadDlg.ui.pushButton_Load.clicked.connect(self.loadInAnswerFile)
        self.answerFileLoadDlg.ui.pushButton_OK.clicked.connect(self.confirmAnswerFile)
        self.encodedAnswerRenameDlg.ui.pushButton_OK.clicked.connect(self.confirmEAnswerFileName)
        self.emailInstructorDlg.ui.pushButton_OK.clicked.connect(self.confirmEmailEntry)
        self.renameWarningDlg.ui.pushButton_OK.clicked.connect(self.renameAllowed)
        self.renameWarningDlg.ui.pushButton_Cancel.clicked.connect(self.renameRejected)
        
#     def generateKeyPairs(self, bits=2048):
#         new_key = RSA.generate(bits, e=65537)
#         public_key = new_key.publickey().exportKey("PEM")
#         private_key = new_key.exportKey("PEM")
#         return private_key, public_key
        
    def renameAllowed(self):
        self.toReplace = True
        self.close()
    
    def renameRejected(self):
        self.toReplace = False
        self.close()
        
    def loadInAnswerFile(self):
        self.answerFile = None
        self.answerFile = QFileDialog.getOpenFileName(self.main, 'Import Student Answer File', directory='./policies/quiz', filter='(*.*);;All Files(*.*)')
        self.answerFile = str(self.answerFile)
        self.answerFileLoadDlg.ui.lineEdit_Dir.setText(self.answerFile)
        rect = QRect(0.3*self.main.geometry().width()+self.main.geometry().x(), 0.3*self.main.geometry().height()+self.main.geometry().y(), self.answerFileLoadDlg.rect().width(), self.answerFileLoadDlg.rect().height())
        self.answerFileLoadDlg.setWindowFlags(self.answerFileLoadDlg.windowFlags()|Qt.WindowStaysOnTopHint)
        self.answerFileLoadDlg.setGeometry(rect)
        self.answerFileLoadDlg.show()
        
    def confirmAnswerFile(self):
        if self.answerFileLoadDlg.ui.lineEdit_Dir.text() != '':
            self.answerFileLoadDlg.close()
            self.readInAnswers()
        else:
            QMessageBox.warning(self, '', 'Please input a file name!')
        
    def confirmEAnswerFileName(self):
        if self.encodedAnswerRenameDlg.ui.lineEdit.text() != '':
            self.eanswerFilename = str(self.encodedAnswerRenameDlg.ui.lineEdit.text())
            self.encodedAnswerRenameDlg.close()
        else:
            QMessageBox.warning(self, '', 'Please input a file name!')
            
    def confirmEmailEntry(self):
        self.main.instructorEmail = str(self.emailInstructorDlg.ui.lineEdit.text())#'manw@mtu.edu'
        self.emailInstructorDlg.close()
        self.encrypt_RSA(self.main.autogradingTest.answers)
        
    def readInAnswers(self):
#         with open(self.answerFile, 'r') as f:
#             message = f.read()
#         # Import key using RSA module
# #         public_key = RSA.importKey(open('./policies/quiz/key.txt').read())
#         # Generate a cypher using the PKCS1.5 standard
#         key = RSA.importKey(self.publicKey)
#         cipher = PKCS1_v1_5.new(key)
#         # Encrypy as bytes
#         encrypted_bytes = cipher.encrypt(message)
#         # Write encrypted string to file
#         print "Writing encrypted string to %s..." % ENCRYPTED_STRING_PATH
#         #ciphertext = encrypted_bytes.encode("base64")
# #         with open(ENCRYPTED_STRING_PATH, "wb") as f:
# #             f.write(encrypted_bytes.encode("base64"))
# #         
# #         with open(ENCRYPTED_STRING_PATH, "rb") as f:
# #             f.write(encrypted_bytes.encode("base64"))
# 
#         # Generate a cypher using the PKCS1.5 standard
# #         key = RSA.importKey(open('./policies/quiz/key_private.txt').read())
#         key = RSA.importKey(self.privateKey)
#         cipher = PKCS1_v1_5.new(key)
#         pt2 = cipher.decrypt(encrypted_bytes, "---")
#         print 'after', pt2
# #         lines = message.split('\n')
# # #         message = 'To be encrypted'
# #         print 'before', message
# #         key = RSA.importKey(open('./policies/quiz/key.txt').read())
# #         cipher = PKCS1_OAEP.new(key)
# # #         ciphertext = ''
# # #         for l in lines:
# # #             cryptLine = cipher.encrypt(l)
# # #             ciphertext+=cryptLine+'\n'
# #         ciphertext = cipher.encrypt(message)
# #         print 'encrypted', ciphertext
# #         with open('./policies/cypherAnswer', 'w') as f:
# #             f.write(ciphertext)
# #         f.close()
# #         
# #         key = RSA.importKey(open('./policies/quiz/key_private.txt').read())
# #         cipher = PKCS1_OAEP.new(key)
# # #         with open('./policies/cypherAnswer', 'r') as f:
# # #             lines = f.readlines()
# #         message = ''
# # #         for l in lines:
# # #             decryptLine = cipher.decrypt()
# # #             message += decryptLine+'\n'
# #         decryptLine = cipher.decrypt(ciphertext)
# #         message += decryptLine+'\n'
# #         print 'after', message
#          
        #self.encrypt_RSA(self.publicKey, message)
        self.decrypt_RSA(self.privateKey, self.answerFile)
        
    def encrypt_RSA(self, message):
#         '''
#         param: public_key_loc Path to public key
#         param: message String to be encrypted
#         return base64 encoded encrypted string
#         '''
#         key = open('./policies/quiz/key.txt', 'r').read()
#         rsakey = RSA.importKey(key)
#         rsakey = PKCS1_OAEP.new(rsakey)
#         encrypted = rsakey.encrypt(message)
#         return encrypted.encode('base64')
        self.answerFileDir = './policies/quiz'#self.answerFile[:self.answerFile.rfind('/')]
        self.answerFile = self.answerFileDir+'/answer.gpg'
        batcmd = 'which gpg'
        if subprocess.call(batcmd, shell=True) == 0:
            while os.path.isfile(self.answerFile):
                self.eanswerFilename = self.answerFile[self.answerFile.rfind('/')+1:]
#                 reply = QMessageBox.warning(self.main, '', "Attempt to save the encrypted file as '"+self.answerFile+"'. But the file '"+self.eanswerFilename+\
#                                              "'already exists under this directory. Would you like to replace it?",\
#                                               QMessageBox.Yes|QMessageBox.No)
#                 self.renameWarningDlg.ui.label.setText("Attempt to save the encrypted file as '"+self.answerFile+"'. But the file '"+self.eanswerFilename+\
#                                               "'already exists under this directory. Would you like to replace it?")
#                 self.renameWarningDlg.show()
                QMessageBox.warning(self.main, '', "Attempt to save the encrypted file as '"+self.answerFile+"'. But the file '"+self.eanswerFilename+\
                                             "'already exists under this directory. Please rename the existing file and click 'OK' to continue!")
#                 if reply == QMessageBox.No:
#                self.answerFile = self.answerFileDir+'/'+self.eanswerFilename
#                 else:
#                     subprocess.call('rm '+self.answerFile, shell=True)
#                     break
            tempFile = self.answerFileDir+'/temp.qiza'
            with open(tempFile, 'w') as f:
                f.write(message)
            encryptCommand = 'gpg --output '+self.answerFile+' --encrypt --recipient '+self.main.instructorEmail+' '+tempFile
            if subprocess.call(encryptCommand, shell=True) == 0:
                subprocess.call('rm '+tempFile, shell=True)
                QMessageBox.critical(self.main, '', "The encrypted answer file has been stored in '"+self.answerFile+\
                                     "'.\nPlease send your answers to the instructor through email and install\nThunderbird for later submissions!")

    def decrypt_RSA(self, privateKey, fileFull):
        decrypted = fileFull[:fileFull.rfind('.')]
#         '''
#         param: public_key_loc Path to your private key
#         param: package String to be decrypted
#         return decrypted string
#         '''
#         key = open('./policies/quiz/key_private.txt', "r").read()
#         rsakey = RSA.importKey(key)
#         rsakey = PKCS1_OAEP.new(rsakey)
#         decrypted = rsakey.decrypt(b64decode(package))
        batcmd = 'which gpg'
        if os.system(batcmd) == 0:
            command = 'gpg --output '+decrypted+' --decrypt --no-tty '+fileFull
            subprocess.call(command, shell=True)
        self.main.hintForDecryption()