#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
#       IBAN-Calculator.py
#       Version 0.2.2
#       
#       Copyright 2013, 2015 Michael Stehmann <info@rechtsanwalt-stehmann.de>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 3 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

# In Debian muessen folgende Pakete zusaetzlich installiert werden:
# -- python3-tk

from tkinter import * 
from tkinter import messagebox


class DialogMaker(object):
	"""Methoden zur Erzeugung und Gestaltung von Tkinter-Dialogen"""

	def __init__(self):
		self.darkbgcolor = "#C7DAE9"
		self.brightcolor = "#F6F9AC"
	
	def makedia(self):
		"""Erzeugt Tkinter-Dialog und setzt Dialogtitel"""
		self.dia=Tk()

	def diatitle (self, title):
		"""Setzt den Titel des Dialogs"""
		self.dia.title(title)

	def mainloop(self):
		"""Erzeugt Dialog"""
		self.dia.mainloop()
		
		"""Creates frame"""	
	def makeframe(self):
		self.frame = Frame(self.dia, borderwidth=2, bg = self.darkbgcolor)
		self.frame.pack(fill="both",expand=1)
		return self.frame

	"""Destroys the frame"""
	def endframe(self):
		self.frame.destroy()	

	def button(self, buttontext, befehl, row_, column_):
		"""Erzeugt Schaltflaeche"""
		auswahlbutton = Button(self.frame, text = buttontext, command = befehl)
		auswahlbutton.grid(row=row_, column=column_, padx=10)

	def endebutton(self, row_, column_):
		"""Erzeugt den Button zum Beenden"""
		eb = Button(self.frame, text = "Ende", fg="red", command = self.ende)
		eb.grid(row=row_, column=column_)

	def ende(self):
		"""Beendet den Dialog"""
		self.dia.destroy()

	# Allgemeine Elemente

	def label(self, ausgabetext, width_, row_, column_, columnspan_=1):
		"""Erzeugt ein Anzeigefeld"""
		lb = Label(self.frame, text = ausgabetext, width=width_, bg=self.brightcolor)
		lb.grid(row=row_, column=column_, columnspan=columnspan_)
		return lb

	def eingabeFeld(self, width_, row_, column_, columnspan_=1):
		"""Erzeugt ein Eingabefeld"""
		e = Entry(self.frame, width=width_)
		e.grid(row=row_, column=column_, columnspan=columnspan_, padx=20)
		return e

	def minfo(self, mbtitle, mbtext, btype="ok"):
		sb = messagebox.showinfo(mbtitle, mbtext, type=btype)
		return sb

	def mwarning(self, mbtitle, mbtext, btype="ok"):
		sb = messagebox.showwarning(mbtitle, mbtext, type=btype)
		return sb

	def merror(self, mbtitle, mbtext, btype="ok"):
		sb = messagebox.showerror(mbtitle, mbtext, type=btype)
		return sb


class MainDialog(DialogMaker):

	def dialog(self):
		self.makedia()
		self.firstframe()
		self.mainloop()
			
	def firstframe(self):
		self.makeframe()
		labeltext = """
Werkzeug zur Ermittlung und Prüfung der IBAN
		
* geschrieben in Python3 von Dr. Michael Stehmann

* veröffentlicht unter der GNU General Public License,
   wie von der Free Software Foundation veröffentlich;
   entweder Version 3 dieser Lizenz oder nach Ihrer
   Wahl jeder späteren Version
"""
		fristlabel = self.label(labeltext, 50, 0, 0, 2)
		fristlabel["font"] = "SansSerif, 12"
		fristlabel["justify"] = "left"
		fristlabel["bg"] = "#C7DAE9"
		self.endebutton(1, 0)
		self.button("Weiter ...", self.warningframe, 1, 1)
				
	def warningframe(self):
		
		self.endframe()
		self.makeframe()
		self.diatitle("Wichtiger Hinweis!")
		labeltext = """
	Wichtiger Hinweis:
	
Die jeweilige IBAN darf nur vom kontoführenden
Institut errechnet und ausgegeben werden.

Die Benutzung selbsterrechneter IBAN
kann zum Rechtsverlust im Falle von Fehlern führen!
""" 
		warninglabel = self.label(labeltext, 50, 0, 0, 2)
		warninglabel["font"] = "SansSerif, 12"
		warninglabel["justify"] = "left"
		warninglabel["bg"] = "#EDF25D"

		self.endebutton(1, 0)
		self.button("Weiter ...", self.makemaindialog, 1, 1)	

	def makemaindialog(self):
		
		self.endframe()
		self.makeframe()
		self.diatitle("IBAN-Calculator")

		self.label("Bankleitzahl", 30, 0, 0)
		self.blz = self.eingabeFeld(30, 1, 0)

		self.label("Kontonummer", 30, 2, 0)
		self.ktonr = self.eingabeFeld(30, 3, 0)

		self.label("Land", 10, 0, 1)
		delabel = self.label("DE", 10, 1, 1)
		delabel["bg"] = "white"

		self.button("IBAN berechnen", self.eingabeauslesen, 4, 0)
		self.endebutton(7, 1)

		self.label("IBAN", 10, 5, 0)
		self.ibanfeld()

		self.button("IBAN prüfen", self.ibantest, 7, 0)

	def ibanfeld(self):

		self.iban = self.eingabeFeld(40, 6, 0, 2)

	def eingabeauslesen(self):

		"""Die Bankleitzahl muss genau 8 Stellen lang sein.
		   Die Kontonummer darf bis zu 10 Stellen Lang sein!
		   Es duerfen mur Ziffern enthaltenm sein."""

		"""Eingabefelder auslesen"""
		_blz = self.blz.get()
		_ktonr = self.ktonr.get()

		if _blz == "" or _ktonr == "":
			self.merror("Eingabe fehlt!", "BLZ und Kontonummer müssen eingegeben werden!")
		else:

			"""Zeichen ersetzen"""
			_blz = _blz.replace(" ","")
			_ktonr = _ktonr.replace(" ","")
			_ktonr = _ktonr.replace("-","")
			_ktonr = _ktonr.replace("/","")

			"""Pruefen, ob nur noch Ziffern vorhanden sind"""
			if [x for x in _blz if x not in "0123456789"]:
				self.merror("BLZ falsch!", "Die Bankleitzahl darf nur Ziffern enthalten!")
			else:
				if [x for x in _ktonr if x not in "0123456789"]:
					self.merror("Kontonummer falsch!", "Die Kontonummer darf nur Ziffern enthalten!")
				else:
					"""Pruefen der Laenge von BLZ und Kontonummer"""
					if not len(_blz) == 8:
						self.merror("BLZ falsch!", "Die Bankleitzahl muss 8 Ziffern enthalten!")
					else:
						if len(_ktonr) > 10:
							self.merror("Kontonummer falsch!", "Die Kontonummer darf nur 10 Ziffern enthalten!")
						else:

							"""Pruefziffern berechnen und IBAN anzeigen"""
							iban = pruefzifferberechnung(_blz, _ktonr)
							self.ibanfeld()
							self.iban.insert(0,iban)

	def ibantest(self):

		"""Testet die Richtigkeit der Pruefziffern der IBAN"""

		"""IBAN-Feld auslesen"""
		_ibanalt = self.iban.get()
		
		"""Leerzeichen löschen"""
		_ibanalt = _ibanalt.replace(" ","")

		"""Eingabe der IBAN pruefen"""
		if len(_ibanalt) != 22:

			_titel = "Falsche Eingabe!"
			_hinweis = "Die IBAN muss genau 22 Zeichen lang sein!"

			if len(_ibanalt) < 22:
				self.merror(_titel, _hinweis+"\nIBAN ist zu kurz!")
			else:
				self.merror(_titel, _hinweis+"\nIBAN ist zu lang!")

		else:

			"""Zerlegung der IBAN"""
			_ibansplit = ibanzerlegung(_ibanalt)

			"""Pruefen, ob deutsche IBAN"""
			if _ibansplit[0] != "DE":
				self.merror("Falsche Eingabe!", "Nur deutsche IBAN können geprüft werden!")
			else:
				"""BLZ und Kontonummer extrahieren"""
				_blz = _ibansplit[2]
				_ktonr = _ibansplit[3]

				"""IBAN mit Pruefziffern neu berechnen"""
				_ibanneu = pruefzifferberechnung(_blz, _ktonr)

				"""Ergebnis der Berechnung mit eingegebener IBAN vergleichen"""
				if _ibanalt == _ibanneu:
					self.minfo("Test bestanden!", "Prüfziffern sind korrekt.")
				else:
					self.mwarning("Achtung!", "Prüfziffern sind falsch!")


def pruefzifferberechnung(blz, ktonr):
	"""Berechnet die Pruefziffer einer deutschen IBAN aus Bankleitzahl
	und Kontonummer"""

	"""Kontonummer auf 10 Stellen mit fuehrenden Nullen auffuellen"""
	if len(ktonr) < 10:
		ktonr10 = (10-len(ktonr)) * "0" + ktonr
	else:
		ktonr10 = ktonr

	"""DE = 1314, die beiden Nullen sind der Dump fuer die Pruefziffern"""
	_ags = blz + ktonr10 + "131400"
	_agz = int(_ags)

	"""Modulo 97 berechnen und von 98 abziehen"""
	_pz = _agz % 97
	_pz = 98 - _pz

	"""Bei einstelliger Pruefziffer eine fuehrende Null auffuellen"""
	if _pz < 10:
		_pzs = "0" + str(_pz)
	else:
		_pzs = str(_pz)

	iban = "DE" + _pzs + blz + ktonr10

	return (iban)

def ibanzerlegung(iban):
	"""Zerlegt eine IBAN in ihre Bestandteile
	und gibt diese als Liste zurueck"""

	i = 0 #Zaehler fuer Zeichen
	_land = ""; _pz = ""; _blz = ""; _ktonr = ""

	for zeichen in iban:
		if i < 2:
			_land = _land + zeichen
		elif i > 1 and i < 4:
			_pz = _pz + zeichen
		elif i > 3 and i < 12:
			_blz = _blz + zeichen
		else:
			_ktonr = _ktonr + zeichen
		i = i+1

	return [_land, _pz, _blz, _ktonr]

def main():
	md = MainDialog()
	md.dialog()

if __name__ == '__main__':
	main()

