/*
 * File:     ExportTigerDialog.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
 */

/* 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.annotator.export;

import mpi.eudico.client.annotator.ElanLocale;
import mpi.eudico.client.annotator.Selection;

import mpi.eudico.client.util.CheckBoxTableCellRenderer;
import mpi.eudico.client.util.Transcription2Tiger;

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

import mpi.eudico.server.corpora.clomimpl.abstr.TierImpl;
import mpi.eudico.server.corpora.clomimpl.type.Constraint;
import mpi.eudico.server.corpora.clomimpl.type.LinguisticType;

import java.awt.Frame;
import java.awt.GridBagConstraints;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;

import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;


/**
 * $Id: ExportTigerDialog.java,v 1.2 2006/03/23 09:22:21 klasal Exp $ Dialog for selecting tiers
 * whose annotations will be exported into the Tiger Syntax Format (as leaf nodes) In
 * "Tiger-terminology": annotations will become feature values of terminal nodes
 *
 * @author $Author: klasal $
 * @version $Revision: 1.2 $
 */
public class ExportTigerDialog extends AbstractTierExportDialog
    implements ListSelectionListener {
    /**DOCUMENT ME! */
    protected static final String TERMINAL_FEATURE_COLUMN = "Terminal feature name";
    private static final String ARROW_COLUMN = "Arrow";
    private JCheckBox restrictCheckBox;
    private Selection selection;
    private Transcription transcription;

    /**
     * Creates a new ExportTigerDialog object.
     *
     * @param parent DOCUMENT ME!
     * @param modal DOCUMENT ME!
     * @param transcription DOCUMENT ME!
     * @param selection DOCUMENT ME!
     */
    public ExportTigerDialog(Frame parent, boolean modal,
        Transcription transcription, Selection selection) {
        super(parent, modal);
        this.transcription = transcription;
        this.selection = selection;
        this.initComponents();
        extractTiers();
        postInit();
    }

    /**
     * Updates the checked state of the export checkboxes.
     *
     * @param lse the list selection event
     */
    public void valueChanged(ListSelectionEvent lse) {
        if ((model != null) && lse.getValueIsAdjusting()) {
            int b = lse.getFirstIndex();
            int e = lse.getLastIndex();
            int col = model.findColumn(EXPORT_COLUMN);

            for (int i = b; i <= e; i++) {
                if (tierTable.isRowSelected(i)) {
                    model.setValueAt(Boolean.TRUE, i, col);
                }
            }
        }
    }

    /**
     * Extract candidate tiers for export.
     */
    protected void extractTiers() {
        if (model != null) {
            for (int i = model.getRowCount() - 1; i >= 0; i--) {
                model.removeRow(i);
            }

            if (transcription != null) {
                LinkedHashMap v = getTerminalTiers(transcription);
                Iterator it = v.keySet().iterator();

                while (it.hasNext()) {
                    List terminalTierList = (List) v.get(it.next());

                    for (int i = 0; i < terminalTierList.size(); i++) {
                        String[] tierString = (String[]) terminalTierList.get(i);
                        model.addRow(new Object[] {
                                Boolean.TRUE, tierString[0], "->", tierString[1]
                            });
                    }
                }
            }
        }
    }

    /**
     * DOCUMENT ME!
     */
    protected void initComponents() {
        super.initComponents();
        model.setColumnIdentifiers(new String[] {
                EXPORT_COLUMN, TIER_NAME_COLUMN, ARROW_COLUMN,
                TERMINAL_FEATURE_COLUMN
            });
        tierTable.getColumn(EXPORT_COLUMN).setCellEditor(new DefaultCellEditor(
                new JCheckBox()));
        tierTable.getColumn(EXPORT_COLUMN).setCellRenderer(new CheckBoxTableCellRenderer());
        tierTable.getColumn(EXPORT_COLUMN).setMaxWidth(30);
        tierTable.getColumn(TERMINAL_FEATURE_COLUMN).setCellEditor(new DefaultCellEditor(
                new JComboBox(Transcription2Tiger.features)));
        tierTable.getColumn(TERMINAL_FEATURE_COLUMN).setMaxWidth(75);
        tierTable.setShowVerticalLines(false);
        tierTable.setTableHeader(null);

        restrictCheckBox = new JCheckBox();

        GridBagConstraints gridBagConstraints = new GridBagConstraints();
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.anchor = GridBagConstraints.WEST;
        gridBagConstraints.insets = insets;
        optionsPanel.add(restrictCheckBox, gridBagConstraints);

        tierTable.getSelectionModel().addListSelectionListener(this);
        updateLocale();
    }

    /**
     * Pack, size and set location.
     */
    protected void postInit() {
        pack();

        int w = 550;
        int h = 400;
        setSize((getSize().width < w) ? w : getSize().width,
            (getSize().height < h) ? h : getSize().height);
        setLocationRelativeTo(getParent());

        //setResizable(false);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     * @throws NullPointerException DOCUMENT ME!
     */
    protected boolean startExport() throws IOException {
        if ((model == null) || (tierTable == null)) {
            throw new NullPointerException("The tier table is null");
        }

        int includeCol = model.findColumn(EXPORT_COLUMN);
        int nameCol = model.findColumn(TIER_NAME_COLUMN);

        // check if there is anything to export
        boolean atLeastOneTier = false;

        for (int i = 0; i < model.getRowCount(); i++) {
            Boolean include = (Boolean) model.getValueAt(i, includeCol);

            if (include.booleanValue()) {
                atLeastOneTier = true;

                break;
            }
        }

        if (!atLeastOneTier) {
            JOptionPane.showMessageDialog(this,
                ElanLocale.getString("ExportTradTranscript.Message.NoTiers"),
                ElanLocale.getString("Message.Warning"),
                JOptionPane.WARNING_MESSAGE);

            return false;
        }

        // prompt for file name and location
        String fileName = promptForFileName("Export.TigerDialog.title");

        if (fileName == null) {
            throw new IOException("No valid output file specified");
        }

        // export....
        ArrayList exportTiers = new ArrayList();
        ArrayList featureNameList = new ArrayList();

        // add selected tiers in the right order
        for (int i = 0; i < model.getRowCount(); i++) {
            Boolean include = (Boolean) model.getValueAt(i, includeCol);

            if (include.booleanValue()) {
                exportTiers.add(model.getValueAt(i, nameCol));
                featureNameList.add(model.getValueAt(i, nameCol + 1));
            }
        }

        String[] tierNames = (String[]) exportTiers.toArray(new String[0]);
        String[] featureNames = (String[]) featureNameList.toArray(new String[0]);

        long selectionBT = 0L;
        long selectionET = Long.MAX_VALUE;

        if (restrictCheckBox.isSelected()) {
            selectionBT = selection.getBeginTime();
            selectionET = selection.getEndTime();
        }

        Transcription2Tiger.exportTiers(transcription, tierNames, featureNames,
            new File(fileName), encoding, selectionBT, selectionET);

        return true;
    }

    /**
     * DOCUMENT ME!
     */
    protected void updateLocale() {
        setTitle(ElanLocale.getString("ExportTigerDialog.Title"));
        titleLabel.setText(ElanLocale.getString("ExportTigerDialog.TitleLabel"));
        tierSelectionPanel.setBorder(new TitledBorder(ElanLocale.getString(
                    "ExportDialog.Label.SelectTiers")));
        optionsPanel.setBorder(new TitledBorder(ElanLocale.getString(
                    "ExportDialog.Label.Options")));
        restrictCheckBox.setText(ElanLocale.getString("ExportDialog.Restrict"));
        startButton.setText(ElanLocale.getString("Button.OK"));
        closeButton.setText(ElanLocale.getString("Button.Close"));
    }

    /**
     * DOCUMENT ME!
     *
     * @param transcription DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    private static LinkedHashMap getTerminalTiers(Transcription transcription) {
        List sentenceTiers = new ArrayList();

        List lingTypes = transcription.getLinguisticTypes();

        for (int i = 0; i < lingTypes.size(); i++) {
            LinguisticType lingType = (LinguisticType) lingTypes.get(i);

            if (lingType.getConstraints() == null) {
                sentenceTiers.addAll(transcription.getTiersWithLinguisticType(
                        ((LinguisticType) lingTypes.get(i)).getLinguisticTypeName()));
            }
        }

        LinkedHashMap terminalTierHash = new LinkedHashMap();

        for (int i = 0; i < sentenceTiers.size(); i++) {
            Tier sentenceTier = (Tier) sentenceTiers.get(i);
            List terminalTierList = new ArrayList();
            List childTiers = ((TierImpl) sentenceTier).getChildTiers();

            for (int j = 0; j < childTiers.size(); j++) {
                Tier childTier = (Tier) childTiers.get(j);

                if (((TierImpl) childTier).getLinguisticType().getConstraints()
                         .getStereoType() == Constraint.TIME_SUBDIVISION) {
                    terminalTierList.add(new String[] {
                            childTier.getName(), Transcription2Tiger.features[0]
                        });

                    List grandChildTiers = ((TierImpl) childTier).getChildTiers();

                    for (int k = 0; k < grandChildTiers.size(); k++) {
                        Tier grandChildTier = (Tier) grandChildTiers.get(k);

                        if (((TierImpl) grandChildTier).getLinguisticType()
                                 .getConstraints().getStereoType() == Constraint.SYMBOLIC_ASSOCIATION) {
                            terminalTierList.add(new String[] {
                                    grandChildTier.getName(),
                                    Transcription2Tiger.features[Math.min(k +
                                        1, Transcription2Tiger.features.length)]
                                });
                        }
                    }
                }

                if (terminalTierList.size() > 0) {
                    terminalTierHash.put(sentenceTier, terminalTierList);
                }
            }
        }

        return terminalTierHash;
    }
}
