/*
 * File:     Transcription2TabDelimitedText.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * 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 2 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.eudico.client.util;

import mpi.eudico.server.corpora.clom.AnnotationCore;
import mpi.eudico.server.corpora.clom.Transcription;

import mpi.eudico.server.corpora.clomimpl.abstr.TierImpl;

import mpi.eudico.util.TimeRelation;

import mpi.search.content.result.model.ContentMatch;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import java.nio.charset.UnsupportedCharsetException;

import java.util.List;


/**
 * Created on Apr 20, 2004 Jun 2005: added optional export of time values in
 * milliseconds
 *
 * @author Alexander Klassmann
 * @version June 30, 2005
 * @version Aug 2005 Identity removed
 */
public class Transcription2TabDelimitedText {
    /** Holds value of property DOCUMENT ME! */
    final static public String TAB = "\t";

    /** Holds value of property DOCUMENT ME! */
    final static private String NEWLINE = "\n";

    /**
     * Exports all annotations on specified tiers
     *
     * @param transcription
     * @param tierNames
     * @param exportFile
     *
     * @throws IOException
     */
    static public void exportTiers(Transcription transcription,
        String[] tierNames, File exportFile) throws IOException {
        exportTiers(transcription, tierNames, exportFile, 0L, Long.MAX_VALUE);
    }

    /**
     * Exports annotations that overlap with specified time interval
     *
     * @param transcription
     * @param tierNames
     * @param exportFile
     * @param beginTime
     * @param endTime
     *
     * @throws IOException
     */
    static public void exportTiers(Transcription transcription,
        String[] tierNames, File exportFile, long beginTime, long endTime)
        throws IOException {
        exportTiers(transcription, tierNames, exportFile, beginTime, endTime,
            true, true, true, true, true, false);
    }

    /**
     * Exports annotations of the specified tiers that overlap the specified
     * interval. Which time information and in which time formats should be
     * included in the output is specified by the last 6 params.
     *
     * @param transcription the source transcription
     * @param tierNames the names of the tiers to export
     * @param exportFile the destination file
     * @param beginTime begin time of the selected interval
     * @param endTime end time of the selected interval
     * @param includeBeginTime if true include the begin time of annotations
     * @param includeEndTime if true include the end time of annotations
     * @param includeDuration if true include the duration of annotations
     * @param includeHHMM if true include the times in hh:mm:ss.ms format
     * @param includeSSMS if true include the times in ss.ms format
     * @param includeMS if true include the times in ms format
     *
     * @throws IOException i/o exception
     */
    static public void exportTiers(Transcription transcription,
        String[] tierNames, File exportFile, long beginTime, long endTime,
        boolean includeBeginTime, boolean includeEndTime,
        boolean includeDuration, boolean includeHHMM, boolean includeSSMS,
        boolean includeMS) throws IOException {
        exportTiers(transcription, tierNames, exportFile, "UTF-8", beginTime,
            endTime, includeBeginTime, includeEndTime, includeDuration,
            includeHHMM, includeSSMS, includeMS);
    }

    /**
     * Exports annotations of the specified tiers that overlap the specified
     * interval. Which time information and in which time formats should be
     * included in the output is specified by the last 6 params.
     *
     * @param transcription the source transcription
     * @param tierNames the names of the tiers to export
     * @param exportFile the destination file
     * @param charEncoding the character encoding
     * @param beginTime begin time of the selected interval
     * @param endTime end time of the selected interval
     * @param includeBeginTime if true include the begin time of annotations
     * @param includeEndTime if true include the end time of annotations
     * @param includeDuration if true include the duration of annotations
     * @param includeHHMM if true include the times in hh:mm:ss.ms format
     * @param includeSSMS if true include the times in ss.ms format
     * @param includeMS if true include the times in ms format
     *
     * @throws IOException i/o exception
     */
    static public void exportTiers(Transcription transcription,
        String[] tierNames, File exportFile, String charEncoding,
        long beginTime, long endTime, boolean includeBeginTime,
        boolean includeEndTime, boolean includeDuration, boolean includeHHMM,
        boolean includeSSMS, boolean includeMS) throws IOException {
        exportTiers(transcription, tierNames, exportFile, charEncoding,
            beginTime, endTime, includeBeginTime, includeEndTime,
            includeDuration, includeHHMM, includeSSMS, includeMS, false, false);
    }

    /**
     * Exports annotations of the specified tiers that overlap the specified
     * interval. Which time information and in which time formats should be
     * included in the output is specified by the last 6 params.
     *
     * @param transcription the source transcription
     * @param tierNames the names of the tiers to export
     * @param exportFile the destination file
     * @param charEncoding the character encoding
     * @param beginTime begin time of the selected interval
     * @param endTime end time of the selected interval
     * @param includeBeginTime if true include the begin time of annotations
     * @param includeEndTime if true include the end time of annotations
     * @param includeDuration if true include the duration of annotations
     * @param includeHHMM if true include the times in hh:mm:ss.ms format
     * @param includeSSMS if true include the times in ss.ms format
     * @param includeMS if true include the times in ms format
     * @param includeSMPTE if true include times in hh:mm:ss:ff format
     * @param palFormat if includeSMPTE is true: use PAL timecode if palFormat is true,
     * otherwise use NTSC drop frame
     *
     * @throws IOException i/o exception
     */
    static public void exportTiers(Transcription transcription,
        String[] tierNames, File exportFile, String charEncoding,
        long beginTime, long endTime, boolean includeBeginTime,
        boolean includeEndTime, boolean includeDuration, boolean includeHHMM,
        boolean includeSSMS, boolean includeMS, boolean includeSMPTE,
        boolean palFormat) throws IOException {
        if (exportFile == null) {
            throw new IOException("No destination file specified for export");
        }

        FileOutputStream out = new FileOutputStream(exportFile);
        OutputStreamWriter osw = null;

        try {
            osw = new OutputStreamWriter(out, charEncoding);
        } catch (UnsupportedCharsetException uce) {
            osw = new OutputStreamWriter(out, "UTF-8");
        }

        BufferedWriter writer = new BufferedWriter(osw);
        AnnotationCore[] annotations = null;

        for (int j = 0; j < tierNames.length; j++) {
            TierImpl tier = (TierImpl) transcription.getTierWithId(tierNames[j]);

            annotations = (AnnotationCore[]) tier.getAnnotations().toArray(new AnnotationCore[0]);

            for (int i = 0; i < annotations.length; i++) {
                if (annotations[i] != null) {
                    if (TimeRelation.overlaps(annotations[i], beginTime, endTime)) {
                        //writer.write(tierNames[j] + getTabString(annotations[i]));
                        writer.write(tierNames[j] +
                            getTabString(annotations[i], includeBeginTime,
                                includeEndTime, includeDuration, includeHHMM,
                                includeSSMS, includeMS, includeSMPTE, palFormat));
                    }
                }
            }
        }

        writer.close();
    }

    /**
     * Exports a List of AnnotationCores to Tab limited text
     *
     * @param tierName DOCUMENT ME!
     * @param annotations
     * @param exportFile
     *
     * @throws IOException
     */
    static public void exportAnnotations(String tierName, List annotations,
        File exportFile) throws IOException {
        if (exportFile == null) {
            return;
        }

        FileOutputStream out = new FileOutputStream(exportFile);
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out,
                    "UTF-8"));

        for (int i = 0; i < annotations.size(); i++) {
            if (annotations.get(i) instanceof AnnotationCore) {
                writer.write(tierName +
                    getTabString((AnnotationCore) annotations.get(i)));
            }
        }

        writer.close();
    }

    /**
     * DOCUMENT ME!
     *
     * @param annotationCore
     *
     * @return String
     */
    static public String getTabString(AnnotationCore annotationCore) {
        return getTabString(annotationCore, true, true);
    }

    /**
     * DOCUMENT ME!
     *
     * @param annotationCore
     * @param HHMMformat if true, output of times in HHMMss.mmm format
     * @param SSMSFormat if true, output of times in second.milliseconds format
     *
     * @return String
     */
    static public String getTabString(AnnotationCore annotationCore,
        boolean HHMMformat, boolean SSMSFormat) {
        return getTabString(annotationCore, true, true, true, HHMMformat,
            SSMSFormat, false);
    }

    /**
     * Creates a tab delimited string with time information and the annotation
     * value.
     *
     * @param annotationCore the annotation
     * @param beginTime include begintime in output
     * @param endTime include endtime in output
     * @param duration include duration in output
     * @param HHMMformat if true, output of times in HHMMss.mmm format
     * @param SSMSFormat if true, output of times in sec.milliseconds format
     * @param MSFormat if true, output of times in milliseconds format
     *
     * @return String the tab seperated result string
     */
    static public String getTabString(AnnotationCore annotationCore,
        boolean beginTime, boolean endTime, boolean duration,
        boolean HHMMformat, boolean SSMSFormat, boolean MSFormat) {
        return getTabString(annotationCore, beginTime, endTime, duration,
            HHMMformat, SSMSFormat, MSFormat, false, false);
    }

    /**
     * Creates a tab delimited string with time information and the annotation
     * value.
     *
     * @param annotationCore the annotation
     * @param beginTime include begintime in output
     * @param endTime include endtime in output
     * @param duration include duration in output
     * @param HHMMformat if true, output of times in HHMMss.mmm format
     * @param SSMSFormat if true, output of times in sec.milliseconds format
     * @param MSFormat if true, output of times in milliseconds format
     * @param SMPTEFormat if true, output times in SMPTE timecode format
     * @param PAL if SMPTEFormat is true and PAL is true use PAL timecode,
     * if SMPTEFormat is true and PAL is false use NTSC drop frame timecode
     *
     * @return String the tab seperated result string
     */
    static public String getTabString(AnnotationCore annotationCore,
        boolean beginTime, boolean endTime, boolean duration,
        boolean HHMMformat, boolean SSMSFormat, boolean MSFormat,
        boolean SMPTEFormat, boolean PAL) {
        StringBuffer sb = new StringBuffer(TAB);

        // begin time
        if (beginTime) {
            if (HHMMformat) {
                sb.append(TimeFormatter.toString(
                        annotationCore.getBeginTimeBoundary()) + TAB);
            }

            if (SSMSFormat) {
                sb.append(Double.toString(
                        annotationCore.getBeginTimeBoundary() / 1000.0) + TAB);
            }

            if (MSFormat) {
                sb.append(annotationCore.getBeginTimeBoundary() + TAB);
            }

            if (SMPTEFormat) {
                if (PAL) {
                    sb.append(TimeFormatter.toTimecodePAL(
                            annotationCore.getBeginTimeBoundary()) + TAB);
                } else {
                    sb.append(TimeFormatter.toTimecodeNTSC(
                            annotationCore.getBeginTimeBoundary()) + TAB);
                }
            }
        }

        // end time
        if (endTime) {
            if (HHMMformat) {
                sb.append(TimeFormatter.toString(
                        annotationCore.getEndTimeBoundary()) + TAB);
            }

            if (SSMSFormat) {
                sb.append(Double.toString(
                        annotationCore.getEndTimeBoundary() / 1000.0) + TAB);
            }

            if (MSFormat) {
                sb.append(annotationCore.getEndTimeBoundary() + TAB);
            }

            if (SMPTEFormat) {
                if (PAL) {
                    sb.append(TimeFormatter.toTimecodePAL(
                            annotationCore.getEndTimeBoundary()) + TAB);
                } else {
                    sb.append(TimeFormatter.toTimecodeNTSC(
                            annotationCore.getEndTimeBoundary()) + TAB);
                }
            }
        }

        // duration
        if (duration) {
            long d = annotationCore.getEndTimeBoundary() -
                annotationCore.getBeginTimeBoundary();

            if (HHMMformat) {
                sb.append(TimeFormatter.toString(d) + TAB);
            }

            if (SSMSFormat) {
                sb.append(Double.toString(d / 1000.0) + TAB);
            }

            if (MSFormat) {
                sb.append(d + TAB);
            }
        }

        sb.append(annotationCore.getValue().replace('\n', ' ') + NEWLINE);

        return sb.toString();
    }
}
