# -*- coding: utf-8 -*-
import functools
import re

import spacy
import textacy
from spacy.tokens import Doc
from spacy.tagger import Tagger

import xml.etree.ElementTree as ET

PARSER = spacy.load('de')
stop_words = list(__import__("spacy." + PARSER.lang, globals(), locals(), ['object']).STOP_WORDS)

def compose(*functions):
    def compose2(f, g):
        return lambda x: f(g(x))
    return functools.reduce(compose2, functions, lambda x: x)


def cleanTexts(textstream, parser, attr):

    #input str-stream output str-stream
    pipe = parser.pipe(textstream)

    for doc in pipe:

        tokens = [tok.text for tok in doc
                  if tok.pos_ not in attr
                  and tok.tag_ not in attr
                  and tok.ent_ not in attr
                  and tok.text not in attr
                  and tok.lower_ not in attr]


        yield " ".join(tokens)


        """
def cleanDoc_lemmatize(doc,parser=PARSER):
    return parser(" ".join([tok.lemma_ for tok in doc ]))


def cleanDoc_STOPS(doc,parser=PARSER, stop_words=None, keep=None):
    if stop_words is None:
        stop_words = list(__import__("spacy." + parser.lang, globals(), locals(), ['object']).STOP_WORDS)

    if hasattr(keep, '__iter__'):
        for k in keep:
            try:
                stop_words.remove(k)
            except ValueError:
                pass

    return parser(" ".join([tok.text for tok in doc if tok.text not in stop_words]))



def cleanDoc_ENT(doc,parser=PARSER, keeponly=False, attr=["WORK_OF_ART", "ORG", "PRODUCT", "LOC"]):
    if keeponly:
        return  parser(" ".join([tok.text for tok in doc if tok.ent_ in attr]))
    else:
        return  parser(" ".join([tok.text for tok in doc if tok.ent_ not in attr]))



def cleanDoc_POS(doc,parser=PARSER, keeponly=False, attr=["SPACE", "PUNCT"]):
    if keeponly:
        return parser(" ".join([tok.text for tok in doc if tok.pos_ in attr]))
    else:
        return parser(" ".join([tok.text for tok in doc if tok.pos_ not in attr]))
"""


def cleanTexts_POS(spacypipe, keeponly=False, attr=["SPACE", "PUNCT"]):
    """
    :param spacypipe: spacypipe
    :param keeponly: bool . If True, only attr will be kept. If false, all attr will be deleted
    :param attr: [str] pos_ or ent_type_
    :yields: stream of strings: full-length cleaned text
    """
    if keeponly:
        for doc in spacypipe:
            yield " ".join([tok.text for tok in doc if tok.pos_ in attr])

    else:
        for doc in spacypipe:
            yield " ".join([tok.text for tok in doc if tok.pos_ not in attr])

def cleanText_POS(text,parser=PARSER, keeponly=False, attr=["SPACE", "PUNCT"]):
    """
    :param txt: str
    :param keeponly: bool . If True, only attr will be kept. If false, all attr will be deleted
    :param attr: [str] pos_ or ent_type_
    :return: str
    """
    doc = parser(text)

    if keeponly:
        return " ".join([tok.text for tok in doc if tok.pos_ in attr])
    else:
        return " ".join([tok.text for tok in doc if tok.pos_ not in attr])


def removeWhitespace(string):
    return re.sub(r'(\r\n|\r|\n|(\s)+)', ' ', string)

def removeWords(string, words):
    big_regex = re.compile('|'.join(map(re.escape, words)))
    return big_regex.sub("", string)






def generateMainTextfromTicketXML(path2xml, main_textfield='Beschreibung', cleaning_function=None):
    """
    generates strings from XML
    :param path2xml:
    :param main_textfield:
    :param cleaning_function:
    :yields strings
    """
    import xml.etree.ElementTree as ET

    tree = ET.parse(path2xml, ET.XMLParser(encoding="utf-8"))
    root = tree.getroot()


    for ticket in root:
        text = "ERROR"
        for field in ticket:
            if field.tag == main_textfield:
                if cleaning_function:
                    text = cleaning_function(field.text)
                else:
                    text = field.text
        yield text

def generateMetadatafromTicketXML(path2xml, key_function_pairs_to_clean, leave_out=['Beschreibung']):
    import xml.etree.ElementTree as ET

    tree = ET.parse(path2xml, ET.XMLParser(encoding="utf-8"))

    root = tree.getroot()

    for ticket in root:
        metadata = {}
        for field in ticket:
            if field.tag not in leave_out:

                if field.tag in key_function_pairs_to_clean:
                    metadata[field.tag] = key_function_pairs_to_clean[field.tag](field.text)
                else:
                    metadata[field.tag] = field.text

        yield metadata




string = "Frau Hinrichs überdenkt die tu Situation a@bc.de und 545453 macht ' dann neue Anträge. \n           Dieses Ticket wird geschlossen \n            \n test"

#print(removeWords(string,["die", "neue"]))

# in:str out:str
cleanString = compose(
    cleanText_POS,
    functools.partial(textacy.preprocess.replace_emails, replace_with=u'EMAIL')
)

key_function_pairs_to_clean = {
    "Loesung":removeWhitespace,
    "Zusammenfassung":cleanText_POS
}
"""
# in:str-gen out:str-gen
cleanStream = compose(
    removeSTOP,
    lemmatize,
    cleanEnt
)
"""
# content: xml -> stringCleaning -> pipe -> docCleaning -> corpus
# metadata:xml -> -> stringCleaning -> corpus

corpus = textacy.Corpus(PARSER)




corpus.add_texts(
    cleanTexts(generateMainTextfromTicketXML("ticketSamples.xml"),PARSER,["PUNCT","SPACE","PERSON"])#,
    #generateMetadatafromTicketXML("ticketSamples.xml",key_function_pairs_to_clean=key_function_pairs_to_clean)
)

print(corpus[0].text)

