#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#==============================================================================
# Copyright (C) 2012 by Loïc Grobol
#
# This file is part of CTESLO.
# 
#    CTESLO 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.
# 
#    CTESLO 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 CTESLO.  If not, see <http://www.gnu.org/licenses/>.
#==============================================================================

"""
Created on 9 janv. 2012

@author: Loïc Grobol <loic.grobol@gmail.com>
"""

import argparse
import sys
import re
import tempfile
import io
import os.path
import copy
import xml.etree.ElementTree as etree

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir
    path.append(dir(dir(path[0])))
    __package__ = "trs"

from libcteslo.dflib.tokenization import DEFAULT_DELIMITERS
from libcteslo.dflib import abstractions as abst


def nb_words(line):
    """Return the number of words in a line."""
    if not line:
        return 0
    words = [word for word in DEFAULT_DELIMITERS.split(line) if word]
    return len(words)


def tag_text(words, get_data):
    """Get tagged lexemes for at least %words words.

    Forgive blank and empty lines."""
    remains = words
    result = []
    while remains > 0:
        data = get_data()
        if data is None:
            data=abst.DataLine(("filler","filler"))
        while len(data)<1:
            data = get_data()
            if data is None:
                data=abst.DataLine(("filler","filler"))
                
        data_text = re.sub("_", " ", data[0])
        element = etree.Element("w", attrib=get_labels(data[-1]))
        element.text = data_text

        result.append(element)
        remains -= nb_words(data_text)
    return result


def normalise_turn(turn, get_data):
    result = etree.Element("Turn", attrib=turn.attrib)
    tagged_text = tag_text(nb_words(turn.text), get_data)
    if tagged_text:
        result.extend(tagged_text)
    for child in turn.getchildren():
        result.append(etree.Element(child.tag, attrib=child.attrib))
        tagged_tail = (tag for tag in tag_text(nb_words(child.tail), get_data) if tag is not None)
        result.extend(tagged_tail)
    return result


def get_labels(label):
    return {"cat": label}

def indent(elem, level=0):
    i = "\n" + level * "  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for elem in elem:
            indent(elem, level + 1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i

def normalise_trs(trs_stream, tag_stream):
    parser = etree.XMLParser(encoding="utf-8")
    tree = etree.parse(trs_stream, parser=parser)
    root = tree.getroot()
    turns = root.findall(".//Turn")
    with abst.datafile_open(tag_stream, mode='r') as tags:
        for turn in turns:
            normalised = normalise_turn(turn, tags.read)
            attrib = copy.deepcopy(turn.attrib)
            turn.clear()
            turn.attrib = attrib
            turn.extend(normalised.getchildren())
    indent(root)
    return tree


def main(argv=sys.argv[1:]):
    """Main function."""
    parser = argparse.ArgumentParser(description="Tag a trs file according to a tagged csv")
    parser.add_argument("--in-stream", "-i",
                         type=argparse.FileType('r'),
                         default=sys.stdin,
                         help="The tagged cvs used to tag")
    parser.add_argument("--trs", "-s",
                         type=argparse.FileType('r'),
                         help="The trs file to tagged.")
    parser.add_argument("--out-stream", "-o",
                         type=argparse.FileType('w'),
                         default=sys.stdout,
                         help="The tagged trs file to be written. Standard output by default.")
    args = parser.parse_known_args(argv)[0] # Get only known args
    if args.in_stream.isatty():
        parser.print_help()
    else:
        with tempfile.TemporaryDirectory(prefix=".cteslo_") as temp:
            xml_tree = os.path.join(temp, "xml_tree")
            normalise_trs(args.trs, args.in_stream).write(xml_tree, encoding='unicode')
            args.out_stream.write("""<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Trans SYSTEM "trans-14.dtd">)
""")
            args.out_stream.write(io.open(xml_tree).read())

if __name__ == "__main__":
    sys.exit(main())
