#!/ usr/bin/python
# -*- coding: utf-8 -*-

""" Einige Rechte vorbehalten. Dieser Code steht unter einer Creative Commons Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen 2.0 Deutschland Lizenz. Author des Codes ist 'kristall aka D.-B. Kierdorf'. Für die Namensnennung ist 'kristall' ausreichend. Fragen, Anmerkungen, Kritik bitte an 'kristall 'ät' c-base.org'"""

""" Dies ist ein 'plug in' für gozerbot 0.8 http://www.gozerbot.org ."""

""" Import der benötigten Module."""
from gozerbot.callbacks import callbacks
from gozerbot.commands import cmnds

import string, re, urllib

from tokens import *
from tokenizer import *

""" Wenn der Bot in einen IRC-Channel eingeloggt ist, dann werden alle Nachrichten in diesem Channel auf Nennung bestimmter deutscher Gesetze überprüft. Wird ein bekanntes Gesetz genannt, so wird versucht eine URL zu der genannten Norm zu finden und das Ergebnis wird dem Nutzer mitgeteilt."""


tokenizer = Tokenizer()
""" Der 'tokenizer' ist die 'Schere' mit der die Nachrichten der Nutzer zerstückelt werden."""

rA = load(open('/home/kristall/python/CBTC/cbtc.rA.unicode',"r"))
""" 'rA' ist der reguläre Ausdruck der das 'Schnittmuster' für den Tokenizer enthält."""

Gesetze = load(open('/home/kristall/python/CBTC/Gesetze.dict',"r"))
""" 'Gesetze' ist ein python dict, das als Schlüssel Gesetze in juristischer Kurznotation verwendet. Der Wert eines Schlüssels ist der Titel des Gesetzes. Beispiel: {u'StGB': u'Strafgesetzbuch', u'BGB': 'Bürgerliches Gesetzbuch'}."""

Parakette = [u'Abs.', u'Nr.', u'Satz', u'Urteilsformel', u'und', u'sowie', u'Rdn.', u'S.', u'Auslagenerstattung', u'Strafhöhe', u'm.w.N.', u'a.F.', u'n.F.', u'Urt.', u'I', u'II', u'III', u'IV', u'V', u'VI', u'VII', u'VIII', u'IX', u'X', u'XI', u'XII', u'XIII', u'XIV', u'XV', u'Nr.', u'a)', u'b)', u'c)', u'd)', u'e)', u'f)',u'g)', u'h)', u'a', u'b', u'c', u'd', u'e', u'f', u'g', u'h', u'i', u'j', u'k', u'(1)', u'(2)', u'(3)', u'(4)', u'(5)', u'(6)', u'(7)', u'(8)', u'(9)', u'(10)', u'(11)', u'(12)', u'(13)', u'(14)', u'(15)', u'(16)', u'(17)', u'(18)', u'(19)', u'(20)']
""" 'Parakette' enthält Wörter die zwischen der Paragraphennummer und dem Gesetz stehen dürfen."""


Probleme = {u'UStG': u'UStG_1980', u'AAG': u'AUFAG', u'A/KAE': u'KAEAANO', u'AAÜG-ÄndG': u'AAÜGÄndG', u'AbfKlärV': u'AbfKlärV_1992', u'AbfVerbrG': u'AbfVerbrG_2007', u'AbgrV': u'AbgrV_1985', u'ABV': u'BLGABV', u'ADNR': u'ADNR_2003', u'AO': u'AO_1977', u'ErbStG': u'ErbStG_1974', u'ErbStDV': u'ErbStDV_1998', u'GrStG': u'GrStG_1973', u'GrEStG': u'GrEStG_1983', u'UWG': u'UWG_2004'}
""" Nicht alle Gesetze können per Regalanwendung aus ihrer Kurznotation in eine URL auf bundesrecht.juris.de übersetzt werden. 'Probleme' enthält als Schlüssel solche Gesetze. Der Wert eines Schlüssels enthält eine korrigierte Kurznotation. Dieses dict enthält nur einen kleinen Teil der Ausnahmen und kann bei Bedarf leicht (z.B. mit einem Script) erweitert werden werden."""


def handle_nachricht(bot, ievent):
    """ Jede Nachricht in einem Channel in den der Bot eingeloggt ist 'triggert' diese Funktion. Die Funktion hat keinen Rückgabewert, sondern schickt gegebenenfalls die erzeugten Antworten an den Channel."""
    Antworten = erzeuge_Antworten(ievent.txt)
    """ 'Antworten' ist eine Liste. 'ievent.txt' enthält die Nachricht eines Nutzers."""
    for Antwort in Antworten:
	ievent.reply(Antwort)
    """ Für jede Antwort in der Liste der Antworten: Sende die Antwort als Nachricht an den Channel.""" 

def erzeuge_Antworten(Nachricht):
    """ Diese Funktion erzeugt die Antwortliste. Dazu wird die Nachricht zerstückelt, die Stücke markiert und die Markierungen ausgewertet. Dabei entsteht als Zwischenergebnis eine Liste aller genannten Normen. Beispiel: Nutzer: 'Also ich glaub das war § 823 II BGB iVm § 185 StGB, oder so ähnlich'; dann entsteht als Zwischenergebnis folgende Liste: ['§ 823 BGB', '§ 185 StGB']. Es wird dann versucht eine URL zu den Normen auf bundesrecht.juris.de und dejure.org zu finden. Außerdem wird der Titel zu den gefundenen Kurznotationen als Antwort angehängt. Rückgabewert ist eine (uU leere) Liste der Rückgabewerte der Funktionen 'existiert_NormURL_auf_bundesrecht(Norm)' und 'existert_NormURL_auf_dejure(Norm)', sowie dem Titel der Normen."""
    Antworten = []
    zu_testen = []
    TokenText = TextToken(Nachricht)
    TokenText = tokenizer.tokenize(TokenText, rA)
    TokenText = tagge_Tokens(TokenText)
    zu_testen = werte_Tags_aus(TokenText)
    for Test in zu_testen:
	Antworten.append(existiert_NormURL_auf_bundesrecht(Test))
	Antworten.append(existiert_NormURL_auf_dejure(Test))
	Antworten.append(u'%s - %s' % (Test[-1], Gesetze[Test[-1]])) 
    #Antworten.append(TokenText['Lexeme'])
    return Antworten

def tagge_Tokens(TokenText):
    """ Diese Funktion schaut sich jedes durch den Tokenizer erzeugte Textstückchen an und vergibt einen PosTag. Der Rückgabewert ist ein Kopie und keine Referenz."""
    Tok = TokenText.copy()
    for Token in Tok['Lexeme']:
	if ((Token['Lexem'] == u'§') or (Token['Lexem'] == u'Art.') or (Token['Lexem'] == u'Artikel')): Token['PosTag'] = u'$Pp'
	elif Token['Lexem'] == u'§§': Token['PosTag'] = u'§PP'
	elif Token['Lexem'] in Parakette: Token['PosTag'] = u'PpK'
	elif Token['Lexem'] in Gesetze: Token['PosTag'] = u'DtG'
    	else:
	    try:
		int(Token['Lexem'])
		Token['PosTag'] = u'CARD'
	    except: 
		try:
		    int(Token['Lexem'][:-1])
		    Token['PosTag'] = u'CARDBK'
		except:
		    Token['PosTag'] = u'XY'
    return Tok

def werte_Tags_aus(TokenText):
    """ Diese Funktion fildet mit Hilfe der PosTags mögliche Normnennungen und erzeugt die Zwischenergebnisliste für die Funktion 'erzeuge_Antworten(Nachricht)'. Rückgabewert ist eine (uU leere) Liste. """
    Sammelbox = []
    Ergebnis = []
    Bedingung01 = False
    Bedingung02 = True
    for Token in TokenText['Lexeme']:
	if Token['PosTag'] == u'$Pp':
            if len(Sammelbox) != 0:
                Sammelbox = []
                Bedingung02 = True
            Sammelbox.append(Token['Lexem'])
            Bedingung01 = True
        elif ((u'CARD' in Token['PosTag']) and (Bedingung01)):
            if Bedingung02:
                Sammelbox.append(Token['Lexem'])
                Bedingung02 = False
        elif ((Token['PosTag'] == u'PpK') and (Bedingung01)):
            pass
        elif ((Token['PosTag'] == u'DtG') and (Bedingung01)):
	    Sammelbox.append(Token['Lexem'])
	    Ergebnis.append(Sammelbox)
	    Antwort = []
            Bedingung01 = False
            Bedingung02 = True
        else:
            Bedingung01 = False
            Bedingung02 = True
            Sammelbox = []
    return Ergebnis

def existiert_NormURL_auf_bundesrecht(Normliste):
    """ Diese Funktion verwandelt eine Norm in eine URL und testet die Existenz der konkreten Norm auf bundesrecht.juris.de, sollte die konkret genannte Norm nicht finden lassen, dann wird versucht zumindest den Index zu dem Gesetz zu finden. Sollte auch dies scheitern wird dies dem Nutzer mitgeteilt. Rückgabewert ist ein String."""
    url = u''
    Norm = Normliste[:]
    if Norm[-1] in Probleme:
	Norm[-1] = Probleme[Norm[-1]]
    Norm[-1] = ersetze_Zeichen(Norm[-1])
    if u'§' in Norm[0]:
	if u'.' in Norm[-1][1]: url = u'http://bundesrecht.juris.de/%s_%s/__%s.html' % (Norm[-1][3:].lower(), Norm[-1][0], Norm[1])
	elif u'.' in Norm[-1][2]: url = u'http://bundesrecht.juris.de/%s_%s/__%s.html' % (Norm[-1][4:].lower(), Norm[-1][0:2], Norm[1])
	else: url = u'http://bundesrecht.juris.de/%s/__%s.html' % (Norm[-1].lower(), Norm[1])
    else: url = u'http://bundesrecht.juris.de/%s/art_%s.html' % (Norm[-1].lower(), Norm[1])
    opener = urllib.FancyURLopener({})
    data = opener.open(url)
    site = unicode(data.read(), 'iso-8859-1')
    if u'404 Not Found' in site:
	if u'.' in Norm[-1][1]: url = u'http://bundesrecht.juris.de/%s_%s/index.html' % (Norm[-1][3:].lower(), Norm[-1][0])
	else: url = u'http://bundesrecht.juris.de/%s/index.html' % (Norm[-1].lower())
	data = opener.open(url)
	site = unicode(data.read(), 'iso-8859-15')
	if u'404 Not Found' in site: return u'Kann leider weder die Norm noch den Index auf bundesrecht.juris.de finden.'
	else: return u'Konkrete Norm nicht, aber %s gefunden.' % (url)
    return url

def ersetze_Zeichen(worin, womit = u'_'):
    """ URLs dürfen eine Reihe von Zeichen nicht enthalten, auf bundesrecht.juris.de werden solche Zeichen durch '_' ersetzt. Diese Funktion ersetzt solche Zeichen durch Unterstriche. Rückgabewert ist ein String der '_' statt verbotener Zeichen enthält."""
    worin = worin.replace(u'Ä', womit)
    worin = worin.replace(u'Ö', womit)
    worin = worin.replace(u'Ü', womit)
    worin = worin.replace(u'ä', womit)
    worin = worin.replace(u'ö', womit)
    worin = worin.replace(u'ü', womit)
    worin = worin.replace(u'ß', womit)
    worin = worin.replace(u' ', womit)
    return worin


def existiert_NormURL_auf_dejure(Normliste):
    """ Diese Funktion überprüft ob eine konkrete Norm auf dejure.org gefunden werden kann. Bei einem Fehlschlag wird auch hier geprüft, ob zumindest ein Index zu dem genannten Gesetz gefunden werden kann. Sollte nix gefunden werden wird keine Nachricht für den Nutzer erzeugt. Rückgabewert ist uU ein String. """
    Umlaute = [u'ä', u'ö', u'ü', u'Ä', u'Ö', u'Ü', u'ß']
    Norm = Normliste[:]
    for Umlaut in Umlaute:
	if Umlaut in Norm[-1]: return
    url = u'http://dejure.org/gesetze/%s' % (Norm[-1])
    opener = urllib.FancyURLopener({})
    data = opener.open(url)
    site = unicode(data.read(), 'iso-8859-1')
    if u'404 Not Found' in site: return
    else:
	url2 = u'%s/%s.html' % (url, Norm[-2])
	data = opener.open(url2)
	file = unicode(data.read(), 'iso-8859-1')
	if u'existiert nicht' in file: return u'Index auf %s vorhanden.' % (url)
	else: return url2

callbacks.add('PRIVMSG', handle_nachricht, threaded=True)
""" Für jede Nachricht in einem Channel rufe 'handle_nachricht()' auf."""

""" Beispiel-Dialog:

<Nutzer> Also dann testen wir mal den § 823 II BGB in Verbindung mit § 185 StGB.
<Bot> http://bundesrecht.juris.de/bgb/__823.html
<Bot> http://dejure.org/gesetze/BGB/823.html
<Bot> BGB - Bürgerliches Gesetzbuch
<Bot> http://bundesrecht.juris.de/stgb/__185.html
<Bot> http://dejure.org/gesetze/StGB/185.html
<Bot> StGB - Strafgesetzbuch
"""
