from tkinter import *
from tkinter import ttk
from tkinter.messagebox import *
from AutoriteCertification import *
from Document import *
from AutoriteHorodatage import *
from SystemeArchivage import SystemeArchivage
from Validations import *


def AC():
	try:
		AC_nom = entree.get()
		AC = AutoriteCertification(AC_nom)
		showinfo("Création autorité de certification", AC_nom + " créé \n"
																" Son certificat expire le " + str(
			AC.get_certificat_racine().get_date_fin_validite()))
	except PrestataireExistingError as err:
		showerror("Création autorité de certification", err.message)


def AH():
	AC_nom = entreeB.get()
	if not AC_nom in AC_dict:
		showerror("Création autorité d'horodatage", "Autorité de certification non existant")
	else:
		try:
			AC = AC_dict[AC_nom]
			AH_nom = entreeA.get()
			AH = AutoriteHorodatage(AH_nom, AC)
			showinfo("Création autorité d'horodatage",
					 AH_nom + " créé \n son certificat a l'ID " + str(AH.get_certificat_ID()) + "\n Il expire le " +
                     str(
						 AH.get_certificat().get_date_fin_validite()))
		except (ClientExistingError, PrestataireExistingError) as err:
			showerror("Création autorité d'horodatage", err.message)


def AH_update():
	AC_nom = entreeB.get()
	AH_nom = entreeA.get()
	if not AC_nom in AC_dict:
		showerror("Certificat d'autorité d'horodatage", "Autorité de certification non existant")
	elif not AH_nom in AH_dict:
		showerror("Certificat d'autorité d'horodatage", "Autorité d'horodatage non existant")
	else:
		AC = AC_dict[AC_nom]
		AH = AH_dict[AH_nom]
		try:
			ID, certificat = AH.changement_certificat(AC)
			showinfo("Certificat d'autorité d'horodatage", AH_nom + " updaté \n "
																	"son nouveau certificat a l'ID : " + str(ID) + "\n"
																												   "Il expire le " + str(
				certificat.get_date_fin_validite()))
		except ClientExistingError as err:
			showerror("Certificat d'autorité d'horodatage", err.message)


def archivage():
	fichier = entree7.get()
	try:
		if fichier in docs_archived:
			showerror("Demande d'archivage", "Document " + fichier + " déjà archivé")
		elif fichier in docs:
			doc = docs[fichier]
			doc.archive_doc(systemeArchivage.AH)
			showinfo("Demande d'archivage", "Document " + fichier + " archivé")
		else:
			raise ArchiveError("Ce système d'archivage n'accepte que des documents signés")
	except FileNotFoundError:
		showerror("Demande d'archivage", "Fichier non existant")
	except ArchiveError as e:
		showerror("Demande d'archivage", e.message)


def certif(new_client):
	nom_prestataire = entree2.get()
	if not nom_prestataire in AC_dict:
		showerror("Demande de certificat", "Prestataire non existant")
	else:
		try:
			nom_client = entree3.get()
			prestataire = AC_dict[nom_prestataire]
			cles, certificat, ID_certificat = prestataire.demande_certificat(nom_client, new_client=new_client)
			showinfo("Demande de certificat", "Certificat de " + nom_client + " créé \n"
																			  "Son ID est " + str(ID_certificat) + "\n"
																												   "Il expire le " + str(
				certificat.get_date_fin_validite()))
		except (ClientExistingError, ClientNotExistingError) as err:
			showerror("Demande de certificat", err.message)


def revoke():
	nom_AC = entree2B.get()
	if not nom_AC in AC_dict:
		showerror("Révocation de certificat", "Prestataire non existant")
	else:
		ID_certificat = entree3B.get()
		if ID_certificat.isdigit() and int(ID_certificat) in certificat_dict:
			certificat = certificat_dict[int(ID_certificat)]
			AC_du_certif = certificat.get_prestataire()
			AC_annonce_dans_interface = AC_dict[nom_AC]
			if AC_du_certif != AC_annonce_dans_interface:
				showerror("Révocation de certificat",
						  "Certificat " + ID_certificat + " non existant chez le prestataire annoncé")
				return
			try:
				AC_du_certif.revocation_certificat(ID_certificat)
				showinfo("Révocation de certificat", "Certificat " + ID_certificat + " révoqué")
			except CertificateRevokedError as err:
				showerror("Révocation de certificat", err.message)
		else:
			showerror("Révocation de certificat", "Certificat " + ID_certificat + " non existant")


def delete_certif():
	nom_AC = entree2C.get()
	if not nom_AC in AC_dict:
		showerror("Suppression de certificat", "Prestataire non existant")
	else:
		ID_certificat = entree3C.get()
		if ID_certificat.isdigit() and int(ID_certificat) in certificat_dict:
			certificat = certificat_dict[int(ID_certificat)]
			AC_du_certif = certificat.get_prestataire()
			AC_annonce_dans_interface = AC_dict[nom_AC]
			if AC_du_certif != AC_annonce_dans_interface:
				showerror("Suppression de certificat",
						  "Certificat " + ID_certificat + " non existant chez le prestataire annoncé")
				return
			try:
				AC_du_certif.oublier_certificat(ID_certificat)
				showinfo("Suppression de certificat", "Certificat " + ID_certificat + " supprimé")
			except CertificateError as e:
				showwarning("Suppression de certificat", "Certificat " + ID_certificat + " supprimé \n" + e.message)
		else:
			print(ID_certificat)
			showerror("Suppression de certificat", "Certificat " + ID_certificat + " non existant")


def signing_basique():
	nom_client = entree4B.get()
	if not nom_client in client_dict:
		showerror("Demande de signature basique", "Client non existant")
	elif nom_client in AH_dict:
		showerror("Demande de signature basique", "Autorité d'horodatage ne peut signer")
	else:
		fichier = entree5B.get()
		client_keys, client_certificate = client_dict[nom_client]
		try:
			if fichier in docs_archived:
				raise SignError("Erreur : Document comporte déjà une signature")
			elif fichier in docs:
				raise SignError("Erreur : Document comporte déjà une signature")
			else:
				doc = Document(fichier)
			private = client_keys["cle_privee"]
			doc.sign_Basique(private, client_certificate)
			showinfo("Demande de signature basique", "Document " + fichier + " signé")
		except SignError as e:
			showerror("Demande de signature basique", "Pour le document " + fichier + "\n" + e.message)
		except FileNotFoundError:
			showerror("Demande de signature basique", "Fichier non existant")


def signing_horodatee():
	AH_nom = entree4H.get()
	if not AH_nom in AH_dict:
		showerror("Demande de signature horodatée", "Autorité d'horodatage non existant")
		return
	AH = AH_dict[AH_nom]
	fichier = entree5H.get()
	try:
		if fichier in docs_archived:
			showerror("Demande de signature horodatée", "Fichier déjà dans le système d'archivage automatique")
		elif fichier in docs:
			doc = docs[fichier]
			doc.sign_Horodatee(AH)
			showinfo("Demande de signature horodatée", "Signature du document " + fichier + " augmenté")
		else:
			showerror("Demande de signature horodatée", "Document sans signature")
	except SignError as e:
		showerror("Demande de signature horodatée", "Pour le document " + fichier + "\n" + e.message)
	except CertificateError as e:
		showerror("Demande de signature horodatée", "Pour le document " + fichier + "\n"
																					"Signature précédente invalide : "
                  + e.message)


def signing_LT():
	fichier = entree5LT.get()
	try:
		if fichier in docs_archived:
			showerror("Demande de signature LT", "Fichier déjà dans le système d'archivage automatique")
		elif fichier in docs:
			doc = docs[fichier]
			doc.sign_LT()
			showinfo("Demande de signature LT", "Signature du document " + fichier + " augmentée")
		else:
			showerror("Demande de signature LT", "Document sans signature")
	except SignError as e:
		showerror("Demande de signature LT", "Pour le document " + fichier + "\n" + e.message)
	except CertificateError as e:
		showerror("Demande de signature LT", "Pour le document " + fichier + "\n"
																			 "Signature précédente invalide : " +
                  e.message)


def signing_LTA():
	AH_nom = entree4LTA.get()
	if not AH_nom in AH_dict:
		showerror("Demande de signature LTA", "Autorité d'horodatage non existant")
	AH = AH_dict[AH_nom]
	fichier = entree5LTA.get()
	try:
		if fichier in docs_archived:
			showerror("Demande de signature LTA", "Fichier déjà dans le système d'archivage automatique")
		elif fichier in docs:
			doc = docs[fichier]
			doc.sign_LTA(AH)
			showinfo("Demande de signature LTA", "Signature du document " + fichier + " augmentée")
		else:
			showerror("Demande de signature LTA", "Document sans signature")
	except SignError as e:
		showerror("Demande de signature LTA", "Pour le document " + fichier + "\n" + e.message)
	
	except FreshnessError as e:
		showerror("Demande de signature LTA", "Pour le document " + fichier + " signature précédente "
																			  "invalide \n" + e.message)


def check_doc():
	fichier = entree6.get()
	if fichier in docs_archived:
		doc = docs_archived[fichier]
	elif fichier in docs:
		doc = docs[fichier]
	else:
		showerror("Vérification de signature", "Fichier non déclaré")
		return
	try:
		signature = doc.get_signature()
		valid, type = check_signature(signature)
		if valid:
			showinfo("Vérification de document",
					 "Signature de type " + type + " pour le document " + fichier + " est valide")
		else:
			showerror("Vérification de document",
					  "Signature de type " + type + " pour le document " + fichier + " est invalide")
	except CertificateError as e:
		showwarning("Vérification de document", "Pour le document " + fichier + "\n"
																				"Vérification indéterminée : " +
                    e.message)
	except FreshnessError as e:
		type = "signature LT"
		showerror("Vérification de document",
				  "Signature de type " + type + " pour le document " + fichier + " est invalide \n" + e.message)


def interface_scrollBar():
	root = Tk()
	root.title("Simulation de signatures électroniques")
	root.geometry("520x580")
	
	main_frame = Frame(root)
	main_frame.pack(fill=BOTH, expand=1)
	
	my_canvas = Canvas(main_frame)
	my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
	
	my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
	my_scrollbar.pack(side=RIGHT, fill=Y)
	
	my_canvas.configure(yscrollcommand=my_scrollbar.set)
	my_canvas.bind("<Configure>", lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))
	
	fenetre = Frame(my_canvas)
	
	my_canvas.create_window((0, 0), window=fenetre, anchor="nw")
	
	return fenetre


def interface_prestataire():
	lcontour = LabelFrame(fenetre, text="Création prestataire")
	lcontour.pack(fill="both", expand="yes")
	l = Frame(lcontour)
	l.pack(anchor=CENTER)
	# frame 1
	Frame1 = Frame(l, borderwidth=2, relief=GROOVE)
	Frame1.pack(side=LEFT, padx=20, pady=5)
	# frame 2
	Frame2 = Frame(l, borderwidth=2, relief=GROOVE)
	Frame2.pack(side=LEFT, padx=20, pady=5)
	# Ajout de labels
	Label(Frame1, text="Autorité de certification").pack(padx=10, pady=10)
	Label(Frame2, text="Autorité d'horodatage").pack(padx=10, pady=10)
	# recupérer info1
	value = StringVar()
	value.set("Nom de AC")
	entree = Entry(Frame1, textvariable=value, width=30)
	entree.pack()
	bouton = Button(Frame1, text="Valider", command=AC)
	bouton.pack()
	# recupérer info2
	value = StringVar()
	value.set("Nom de AH")
	entreeA = Entry(Frame2, textvariable=value, width=30)
	entreeA.pack()
	value = StringVar()
	value.set("Nom de AC")
	entreeB = Entry(Frame2, textvariable=value, width=30)
	entreeB.pack()
	bouton = Button(Frame2, text="Valider", command=AH)
	bouton.pack()
	bouton = Button(Frame2, text="Changer de certificat", command=AH_update)
	bouton.pack()
	return entree, entreeA, entreeB


def interface_certificat():
	lcontour = LabelFrame(fenetre, text="Certificat : demande, révocation et suppression")
	lcontour.pack(fill="both", expand="yes")
	l2 = Frame(lcontour)
	l2.pack(anchor=CENTER)
	# frame 1
	Frame1 = Frame(l2, borderwidth=2, relief=GROOVE)
	Frame1.pack(side=LEFT, padx=10, pady=5)
	# frame 2
	Frame2 = Frame(l2, borderwidth=2, relief=GROOVE)
	Frame2.pack(side=LEFT, padx=10, pady=5)
	# frame 2
	Frame3 = Frame(l2, borderwidth=2, relief=GROOVE)
	Frame3.pack(side=LEFT, padx=10, pady=5)
	# Ajout de labels
	Label(Frame1, text="Demande de certificat").pack(padx=10, pady=10)
	Label(Frame2, text="Révocation de certificat").pack(padx=10, pady=10)
	Label(Frame3, text="Suppression de certificat").pack(padx=10, pady=10)
	
	value2 = StringVar()
	value2.set("Nom de AC")
	entree2 = Entry(Frame1, textvariable=value2, width=30)
	entree2.pack()
	value3 = StringVar()
	value3.set("Nom du client")
	entree3 = Entry(Frame1, textvariable=value3, width=30)
	entree3.pack()
	bouton = Button(Frame1, text="Valider", command=lambda: certif(new_client=True))
	bouton.pack()
	bouton = Button(Frame1, text="Changer de certificat", command=lambda: certif(new_client=False))
	bouton.pack()
	
	value = StringVar()
	value.set("Nom de AC")
	entree2B = Entry(Frame2, textvariable=value, width=30)
	entree2B.pack()
	value3 = StringVar()
	value3.set("ID du certificat")
	entree3B = Entry(Frame2, textvariable=value3, width=30)
	entree3B.pack()
	bouton = Button(Frame2, text="Valider", command=revoke)
	bouton.pack()
	
	value = StringVar()
	value.set("Nom de AC")
	entree2C = Entry(Frame3, textvariable=value, width=30)
	entree2C.pack()
	value3 = StringVar()
	value3.set("ID du certificat")
	entree3C = Entry(Frame3, textvariable=value3, width=30)
	entree3C.pack()
	bouton = Button(Frame3, text="Valider", command=delete_certif)
	bouton.pack()
	
	return entree2, entree3, entree2B, entree3B, entree2C, entree3C


def interface_archivage():
	l = LabelFrame(fenetre, text="Archivage", padx=20, pady=5)
	l.pack(fill="both", expand="yes")
	value = StringVar()
	value.set("Chemin vers le fichier.txt")
	entree7 = Entry(l, textvariable=value, width=22)
	entree7.pack()
	bouton = Button(l, text="Valider", command=archivage)
	bouton.pack()
	
	return entree7


def interface_sign_horo():
	l3 = LabelFrame(fenetre, text="Signature basique & augmentations", padx=20, pady=5)
	l3.pack(fill="both", expand="yes")
	# frame Basique
	Frame1 = Frame(l3, borderwidth=2, relief=GROOVE)
	Frame1.pack(side=LEFT, padx=10, pady=5)
	# frame Horodatee
	Frame2 = Frame(l3, borderwidth=2, relief=GROOVE)
	Frame2.pack(side=LEFT, padx=10, pady=5)
	# frame LT
	Frame3 = Frame(l3, borderwidth=2, relief=GROOVE)
	Frame3.pack(side=LEFT, padx=10, pady=5)
	# frame LTA
	Frame4 = Frame(l3, borderwidth=2, relief=GROOVE)
	Frame4.pack(side=LEFT, padx=10, pady=5)
	# Ajout de labels
	Label(Frame1, text="Signature Basique").pack(padx=10, pady=5)
	Label(Frame2, text="Signature Horodatée").pack(padx=10, pady=5)
	Label(Frame3, text="Signature LT").pack(padx=10, pady=5)
	Label(Frame4, text="Signature LTA").pack(padx=10, pady=5)
	# recupérer info basique
	value4 = StringVar()
	value4.set("Nom du client")
	entree4B = Entry(Frame1, textvariable=value4, width=22)
	entree4B.pack()
	value5 = StringVar()
	value5.set("Chemin vers le fichier.txt")
	entree5B = Entry(Frame1, textvariable=value5, width=22)
	entree5B.pack()
	bouton = Button(Frame1, text="Valider", command=signing_basique)
	bouton.pack()
	# recupérer info horodatee
	value = StringVar()
	value.set("Nom de AH")
	entree4H = Entry(Frame2, textvariable=value, width=22)
	entree4H.pack()
	value = StringVar()
	value.set("Chemin vers le fichier.txt")
	entree5H = Entry(Frame2, textvariable=value, width=22)
	entree5H.pack()
	bouton = Button(Frame2, text="Valider", command=signing_horodatee)
	bouton.pack()
	# recupérer info LT
	value = StringVar()
	value.set("Chemin vers le fichier.txt")
	entree5LT = Entry(Frame3, textvariable=value, width=22)
	entree5LT.pack()
	bouton = Button(Frame3, text="Valider", command=signing_LT)
	bouton.pack()
	# recupérer info LTA
	value = StringVar()
	value.set("Nom de AH")
	entree4LTA = Entry(Frame4, textvariable=value, width=22)
	entree4LTA.pack()
	value = StringVar()
	value.set("Chemin vers le fichier.txt")
	entree5LTA = Entry(Frame4, textvariable=value, width=22)
	entree5LTA.pack()
	bouton = Button(Frame4, text="Valider", command=signing_LTA)
	bouton.pack()
	
	return entree4B, entree5B, entree4H, entree5H, entree5LT, entree4LTA, entree5LTA


def interface_verification():
	l4 = LabelFrame(fenetre, text="Vérification d'un document signé", padx=20, pady=5)
	l4.pack(fill="both", expand="yes")
	value6 = StringVar()
	value6.set("Chemin vers le fichier.txt")
	entree6 = Entry(l4, textvariable=value6, width=22)
	entree6.pack()
	bouton = Button(l4, text="Valider", command=check_doc)
	bouton.pack()
	
	return entree6


if __name__ == "__main__":
	systemeArchivage = SystemeArchivage("AC_archivage", "AH_archivage")
	systemeArchivage.start()
	
	fenetre = interface_scrollBar()
	entree, entreeA, entreeB = interface_prestataire()
	entree2, entree3, entree2B, entree3B, entree2C, entree3C = interface_certificat()
	entree4B, entree5B, entree4H, entree5H, entree5LT, entree4LTA, entree5LTA = interface_sign_horo()
	entree6 = interface_verification()
	entree7 = interface_archivage()
	
	bouton = Button(fenetre, text="Fermer", command=fenetre.quit)
	bouton.pack()
	fenetre.mainloop()