/*
 * $Id: RTFExtractor.java,v 1.21 2005/09/13 09:51:43 jonyp Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: RTFExtractor.java,v $
 * Revision 1.21  2005/09/13 09:51:43  jonyp
 * cleaning the code
 *
 * Revision 1.20  2005/06/30 13:51:19  marbobo
 * + layout angepasst
 *
 * Revision 1.19  2005/04/01 00:12:10  marbobo
 * + UTF-8 Parsing vervollständigt und korrigiert
 *
 * Revision 1.18  2005/03/29 14:34:55  lawern
 * Anpassung an Unicode-fähigen RTF-Parser
 *
 * Revision 1.17  2005/03/24 12:57:05  lawern
 * Umstellung des TDF-Formats auf Version 1.1 in UTF-8-Kodierung.
 *
 * Revision 1.16  2004/11/10 15:02:43  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.15  2004/06/27 17:12:46  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.14  2003/12/24 10:12:01  bigmac
 * Projektweite Import-Optimierung
 *
 * Revision 1.13  2003/09/22 07:35:41  lawern
 * Codierung von < und > in TDF-Dokumenten erweitert.
 *
 * Revision 1.12  2003/08/07 09:13:01  lawern
 * Fehler in addLastElement() beseitigt.
 *
 * Revision 1.11  2003/07/25 12:16:15  lawern
 * vergessenes Close hinzugefügt
 *
 * Revision 1.10  2003/07/24 12:45:54  lawern
 * LogManager wird jetzt auch verwendet.
 *
 * Revision 1.9  2003/07/22 07:36:58  lawern
 * Bugfix
 *
 * Revision 1.8  2003/07/21 10:34:29  lawern
 * Es werden jetzt auch Beschreibung und Schlagwörter ausgelesen.
 *
 * Revision 1.7  2003/07/18 14:05:38  lawern
 * erste funktionsfähige Version mit Majix-RTF-Parser
 *
 * Revision 1.6  2003/07/17 14:20:27  lawern
 * Komplettumbau mit dem Majix-RTF-Parser
 *
 * Revision 1.5  2003/07/01 11:33:13  lawern
 * Temporäre RTF-Datei wird jetzt gelöscht.
 *
 * Revision 1.4  2003/06/30 07:17:01  lawern
 * Dokumenttitel werden jetzt geholt.
 *
 * Revision 1.3  2003/06/27 12:47:20  lawern
 * Code aufgeräumt
 *
 * Revision 1.2  2003/06/27 12:22:24  lawern
 * RTFExtractor eingebunden
 *
 * Revision 1.1  2003/06/27 11:55:51  lawern
 * initiale Version
 *
 */
package vkc.converter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import vkc.analyse.TextStyle;
import vkc.analyse.TextStyles;
import vkc.converter.rtf.RtfAnalyser;
import vkc.converter.rtf.RtfCompoundObject;
import vkc.converter.rtf.RtfDocument;
import vkc.converter.rtf.RtfInfo;
import vkc.converter.rtf.RtfReader;
import vkc.misc.VKCLogManager;
import vkc.util.VKCUtils;


/**
 * Diese Klasse extrahiert aus einem RTF-Dokument den Text und gewichtet diesen
 * auf Basis der verwendeten typographischen Styles (Schriftgröße,
 * Kursivschrift usw.). Es wirkt sich sicherlich zeitsparend aus, wenn man
 * Objekte dieses Typs mehrfach verwendet.
 *
 * @author lawern
 */
public final class RTFExtractor {
    public static final boolean debug = false;
    private boolean rendered;
    private ArrayList links = new ArrayList();
    private TextStyles elements;
    private String documentTitle;
    private String documentKeywords;
    private String documentDescription;
    private RtfDocument doc = null;
    private int lastFontSize = -1;
    private boolean lastBold = false;
    private boolean lastItalic = false;
    private boolean lastUnderlined = false;
    private String fragmentText = "";
    private boolean newLine = false;
    private boolean separated = false;
    private boolean elementNewLine = true;
    private boolean elementSeparated = false;

    public RTFExtractor() {
        //Link-Liste löschen
        links.clear();

        //Style-Statistik neu anlegen
        elements = new TextStyles();

        documentTitle = null;
    }

    public void analyse(String file) {
        RtfReader reader;

        try {
            reader = new RtfReader(file);
        } catch (IOException e) {
            VKCLogManager.errorLog(this, "1", "File not found : " + file, e);

            return;
        }

        RtfAnalyser ana = new RtfAnalyser(reader, null);

        doc = ana.parse();

        if (doc != null) {
            analyse(doc);
        }

        reader.close();

        //letztes Element noch wegschreiben
        addLastElement();

        documentTitle = doc.getInfo().getProperty(RtfInfo.TITLE);

        documentKeywords = doc.getInfo().getProperty(RtfInfo.KEYWORDS);
        documentDescription = doc.getInfo().getProperty(RtfInfo.DOCCOMM);

        rendered = true;
    }

    /**
     * Gibt eine Liste zurueck, der alle HREFs einer Seite enthaelt.
     *
     * @return Link-Vektor
     */
    public ArrayList getLinks() {
        if (rendered) {
            return links;
        } 

        return null;
    }

    /**
     * Liefert eine Liste mit Objekten vom Typ TextStyle zurück, welche das
     * gerenderte RTF-Dokument beschreiben.
     *
     * @return Liste mit Objekten vom Typ TextStyle
     */
    public TextStyles getElements() {
        if (rendered) {
            return elements;
        } 

        return null;
    }

    /**
     * Schreibt eine Datei mit Gewichtungsmarken in ein byte[]
     *
     * @return Array, welches die Datei enthält
     */
    public byte[] getTdfArray() {
        ByteArrayOutputStream array = new ByteArrayOutputStream();
        PrintStream out;
		try {
			out = new PrintStream(array, false, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}

        if (rendered) {
            TextStyle actStyle = null;

            out.println("<V:1.1>");

            String docTitle = VKCUtils.tdfEncode(documentTitle);
            out.print("<T:\u200E" + docTitle + "\u200E>");

            String text;

            for (int i = 0; i < elements.size(); i++) {
                actStyle = (TextStyle) elements.get(i);

                //neue Zeile?
                if (actStyle.newLine) {
                    out.println("");

                    //neuer Absatz?
                    if (actStyle.separated) {
                        out.println("<P>");
                    }
                }

                text = VKCUtils.tdfEncode(actStyle.text);
                out.print("<S:" + actStyle.weight + ": " + text + " >");
            }
        }

        return array.toByteArray();
    }

    /**
     * Gibt den Titel des aktuell gerenderten Dokuments zurück
     *
     * @return Titel des Dokuments
     */
    public String getTitle() {
        if (rendered) {
            return documentTitle;
        } 

        return null;
    }

    /**
     * Gibt die Beschreibung des aktuell gerenderten Dokuments zurück
     *
     * @return Beschreibung des Dokuments
     */
    public String getDescription() {
        if (rendered) {
            return documentDescription;
        } 

        return null;
    }

    /**
     * Gibt die Schlagwörter des aktuell gerenderten Dokuments zurück
     *
     * @return Schlagwörter des Dokuments
     */
    public String getKeyWords() {
        if (rendered) {
            return documentKeywords;
        } 

        return null;
    }

    public void analyse(RtfCompoundObject objects) {
        for (int ii = 0; ii < objects.size(); ii++) {
            if (objects.getObject(ii) == null) {
                System.out.println("bad !");

                continue;
            }

            objects.getObject(ii).generate(this);
        }
    }

    /**
     * Fügt ein neues Text-Objekt zu den TDF-Elements hinzu.
     */
    public void addLastElement() {
        fragmentText = fragmentText.trim();

        if (fragmentText.length() > 0) {
            elements.add(new TextStyle(lastFontSize, lastBold, lastItalic,
                    lastUnderlined, fragmentText, elementNewLine,
                    elementSeparated));

            //            System.out.println("size:" + lastFontSize + ",bold:" + lastBold +
            //                ",separated:" + elementSeparated + ",newLine:" +
            //                elementNewLine + ",text:" + fragmentText.trim());
        }

        fragmentText = "";
        lastFontSize = -1;
        elementSeparated = separated;
        elementNewLine = newLine;
        separated = false;
        newLine = false;
    }

    /**
     * Erweitert das letzte Element oder erzeugt ein neues.
     */
    public void addFragment(String text, int fontSize, boolean bold,
        boolean italic, boolean underlined) {
    	
        // sieht das letzte Fragment aus wie dieses und gab es keinen Zeilen-
        // oder Absatzwechsel?
        if ((fontSize == lastFontSize) && (bold == lastBold) &&
                (italic == lastItalic) && (underlined == lastUnderlined)) { // &&
            fragmentText += text;
        } else {
            //Nein, letztes Element wegschreiben und neues anlegen
            if (lastFontSize != -1) {
                //altes Element nur hinzufügen, wenn es gültig ist
                addLastElement();
            }

            fragmentText = text;
            lastFontSize = fontSize;
            lastBold = bold;
            lastItalic = italic;
            lastUnderlined = underlined;
        }
    }

    /**
     * Fügt einen Link in die Linkliste ein.
     */
    public void addLink(String link) {
        links.add(link);
    }

    /**
     * Wenn noch kein Leerzeichen hinter dem letzten Wort ist, wird hier eins
     * eingefügt, weil ansosnten die Wörter verschmelzen.
     */
    public void addTabulator() {
        fragmentText = fragmentText.trim() + " ";
    }

    /**
     * Signalisiert einen Zeilenwechsel.
     */
    public void newLine() {
        newLine = true;
        addLastElement();

        //System.out.println("new Line");
    }

    /**
     * Signalisiert einen Absatzwechsel.
     */
    public void separated() {
        newLine = true;
        separated = true;
        addLastElement();

        //System.out.println("new Paragraph");
    }

    public static void main(String[] args) {
        VKCLogManager.init( "c:/temp/test_", ".log" );
        VKCLogManager.setEnableLogging(true);
        VKCLogManager.setLogToConsole(true);
        
        RTFExtractor extractor = new RTFExtractor();
        extractor.analyse(args[0]);

        System.out.println(new String(extractor.getTdfArray()));
        System.exit(0);

        //org.jutils.runtime.ThreadLister.main(new String[1]);
    }
}
