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

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

import mpi.eudico.client.annotator.gui.TextExportFileChooser;

import mpi.eudico.client.annotator.tier.TierExportTableModel;

import mpi.eudico.client.annotator.util.ElanFileFilter;
import mpi.eudico.client.annotator.util.FileExtension;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

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

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileFilter;


/**
 * Abstract dialog class for tier export.
 *
 * @author Han Sloetjes
 */
public abstract class AbstractTierExportDialog extends JDialog
    implements ActionListener {
    /** title label */
    protected JLabel titleLabel;

    /** title panel */
    protected JPanel titlePanel;

    /** panel for a tier table */
    protected JPanel tierSelectionPanel;

    /** table for tiers */
    protected JTable tierTable;

    /** table model for tier table */
    protected TierExportTableModel model;

    /** panel for options ui elements */
    protected JPanel optionsPanel;

    /** panel for start and close buttons */
    protected JPanel buttonPanel;

    /** start export button */
    protected JButton startButton;

    /** close button */
    protected JButton closeButton;

    /** column id for the include in export checkbox column, invisible */
    protected final String EXPORT_COLUMN = "export";

    /** column id for the tier name column, invisible */
    protected final String TIER_NAME_COLUMN = "tier";

    /** insets for ui components */
    protected Insets insets = new Insets(2, 6, 2, 6);

    /** Character Encoding of export file */
    protected String encoding = "UTF-8";

    /**
     * Creates a new AbstractTierExportDialog instance.
     *
     * @param parent the parent frame
     * @param modal whether this dialog should be modal
     */
    public AbstractTierExportDialog(Frame parent, boolean modal) {
        super(parent, modal);
    }

    /**
     * Initializes UI elements.
     */
    protected void initComponents() {
        titleLabel = new JLabel();
        titlePanel = new JPanel();
        tierSelectionPanel = new JPanel();
        optionsPanel = new JPanel();
        buttonPanel = new JPanel();
        startButton = new JButton();
        closeButton = new JButton();
        model = new TierExportTableModel();
        tierTable = new JTable(model);

        getContentPane().setLayout(new GridBagLayout());
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

        addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent evt) {
                    closeDialog(evt);
                }
            });

        GridBagConstraints gridBagConstraints;

        titlePanel.setLayout(new BorderLayout(0, 4));
        titleLabel.setFont(titleLabel.getFont().deriveFont((float) 16));
        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);

        JPanel titleLabelPanel = new JPanel();
        titleLabelPanel.add(titleLabel);
        titlePanel.add(titleLabelPanel, BorderLayout.NORTH);

        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = insets;
        getContentPane().add(titlePanel, gridBagConstraints);

        tierSelectionPanel.setLayout(new GridBagLayout());

        Dimension tableDim = new Dimension(50, 100);

        JScrollPane tierScrollPane = new JScrollPane(tierTable);
        tierScrollPane.setPreferredSize(tableDim);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = insets;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        tierSelectionPanel.add(tierScrollPane, gridBagConstraints);

        // add more elements to this panel
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = insets;
        getContentPane().add(tierSelectionPanel, gridBagConstraints);

        optionsPanel.setLayout(new GridBagLayout());

        // add elements to the optionspanel
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = GridBagConstraints.WEST;
        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = insets;
        getContentPane().add(optionsPanel, gridBagConstraints);

        buttonPanel.setLayout(new GridLayout(1, 2, 6, 0));

        startButton.addActionListener(this);
        buttonPanel.add(startButton);

        closeButton.addActionListener(this);
        buttonPanel.add(closeButton);

        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.insets = insets;
        getContentPane().add(buttonPanel, gridBagConstraints);
    }

    /**
     * Set the localized text on ui elements
     */
    protected abstract void updateLocale();

    /**
     * Starts the actual export after performing some checks.
     *
     * @return true if export succeeded, false oherwise
     */
    protected abstract boolean startExport() throws IOException;

    /**
     * Closes the dialog
     *
     * @param evt the window closing event
     */
    protected void closeDialog(WindowEvent evt) {
        setVisible(false);
        dispose();
    }

    /**
     * The action performed event handling.
     *
     * @param ae the action event
     */
    public void actionPerformed(ActionEvent ae) {
        Object source = ae.getSource();

        if (source == startButton) {
            try {
                boolean success = startExport();

                if (success) {
                    closeDialog(null);
                } else {
                    // do nothing
                }
            } catch (Exception ee) {
                JOptionPane.showMessageDialog(this,
                    ElanLocale.getString("ExportDialog.Message.Error") + "\n" +
                    "(" + ee.getMessage() + ")",
                    ElanLocale.getString("Message.Error"),
                    JOptionPane.ERROR_MESSAGE);
            }
        } else if (source == closeButton) {
            closeDialog(null);
        }
    }

    /**
     * Prompts the user for a file name and location.
     *
     * @return a file (unique) path
     */
    protected String promptForFileName(String chooserTitle) {
        String exportDir = (String) Preferences.get("LastUsedExportDir", null);

        if (exportDir == null) {
            exportDir = System.getProperty("user.dir");
        }

        TextExportFileChooser chooser = new TextExportFileChooser();
        chooser.setCurrentDirectory(new File(exportDir));
        chooser.setDialogTitle(chooserTitle);

        File exportFile = null;
        FileFilter filter = ElanFileFilter.createFileFilter(ElanFileFilter.TEXT_TYPE);
        chooser.setFileFilter(filter);

        if (chooser.showSaveDialog(null, null) == JFileChooser.APPROVE_OPTION) {
            File curDir = chooser.getCurrentDirectory();

            if (curDir != null) {
                Preferences.set("LastUsedExportDir", curDir.getAbsolutePath(),
                    null);
            }

            exportFile = chooser.getSelectedFile();

            if (exportFile != null) {
                encoding = chooser.getSelectedEncoding();

                String name = exportFile.getAbsolutePath();
                String lowerPathName = name.toLowerCase();

                String[] exts = FileExtension.TEXT_EXT;
                boolean validExt = false;

                for (int i = 0; i < exts.length; i++) {
                    if (lowerPathName.endsWith("." + exts[i])) {
                        validExt = true;

                        break;
                    }
                }

                if (!validExt) {
                    name += ("." + exts[0]);
                    exportFile = new File(name);
                }

                if (exportFile.exists()) {
                    int answer = JOptionPane.showConfirmDialog(null,
                            ElanLocale.getString("Message.Overwrite"),
                            ElanLocale.getString("SaveDialog.Message.Title"),
                            JOptionPane.YES_NO_OPTION);

                    if (answer == JOptionPane.NO_OPTION) {
                        return promptForFileName(chooserTitle);
                    } else {
                        return name;
                    }
                } else {
                    return name;
                }
            } else {
                return null;
            }
        } else {
            // save dialog canceled
            return null;
        }
    }
}
