/*
 * File:     ImportShoeboxWAC.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.gui;

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

import mpi.eudico.client.annotator.util.*;

import mpi.eudico.server.corpora.clomimpl.shoebox.ShoeboxPreferences;
import mpi.eudico.server.corpora.clomimpl.shoebox.ShoeboxTypFile;

import java.awt.BorderLayout;
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.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.io.File;

import java.util.Hashtable;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;


/**
 * Displays a dialog to either import a WAC file or a Shoebox file. Uses a
 * JOptionPane style mechanism to display a JDialog and return an Object as a
 * user value.<br>
 * <b>Note: </b>localization of the file choosers is not implemented (yet).
 *
 * @author Han Sloetjes
 */
public class ImportShoeboxWAC extends JComponent implements ActionListener,
    ItemListener {
    /** Holds value of property DOCUMENT ME! */
    public static final int SHOEBOX = 0;

    /** Holds value of property DOCUMENT ME! */
    public static final int WAC = 1;
    private static int importType;

    /** Holds value of property DOCUMENT ME! */
    public static final String VALUE_PROPERTY = "value";

    /** Holds value of property DOCUMENT ME! */
    public static final String TEXT_KEY = "TextFile";

    /** Holds value of property DOCUMENT ME! */
    public static final String TYPE_KEY = "TypeFile";

    /** Holds value of property DOCUMENT ME! */

    //    public static final String MEDIA_KEY = "MediaFile";
    private JTextField sbxField = new JTextField("", 23);
    private JTextField typField = new JTextField("", 23);

    //    private JTextField auField = new JTextField("", 23);
    private GridBagLayout gridbag = new GridBagLayout();
    private GridBagConstraints gbc = new GridBagConstraints();
    private JButton txtButton;
    private JButton typButton;

    //    private JButton medButton;
    private JButton fieldSpecButton;
    private JButton okButton;
    private JButton cancelButton;
    private JRadioButton typeRB;
    private JRadioButton specRB;
    private JLabel typeLabel;
    private JLabel intervalLabel;
    private JTextField intervalField;
    private final String INTERVAL_PREF = "ShoeboxChatBlockDuration";

    //	private File lastUsedDir;//used for elan properties file

    /** Used for the storage of the filenames and media files */
    private Hashtable fileNames = new Hashtable();

    //    private Vector mediaFileNames;
    private Object value;

    /**
     * Creates a new ImportShoeboxWAC instance
     *
     * @param type either <code>WAC</code> or <code>SHOEBOX</code>
     */
    private ImportShoeboxWAC(int type) {
        if (type == WAC) {
            importType = WAC;
        } else {
            importType = SHOEBOX;
        }

        createPane();
    }

    private void createPane() {
        setLayout(gridbag);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(3, 3, 3, 3);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 0.0;

        ButtonGroup buttonGroup = new ButtonGroup();
        typeRB = new JRadioButton();
        typeRB.setSelected(true);

        //typeRB.addItemListener(this);
        specRB = new JRadioButton();

        //specRB.addItemListener(this);
        buttonGroup.add(typeRB);
        buttonGroup.add(specRB);

        if (importType == SHOEBOX) {
            add(typeRB, gbc);
            gbc.gridy++;
            add(specRB, gbc);
        }

        gbc.gridx = 1;
        gbc.gridy = 0;

        if (importType == WAC) {
            add(new JLabel(ElanLocale.getString("ImportDialog.Label.WAC")), gbc);
        } else {
            add(new JLabel(ElanLocale.getString("ImportDialog.Label.Shoebox")),
                gbc);
        }

        gbc.gridy++;
        typeLabel = new JLabel(ElanLocale.getString("ImportDialog.Label.Type"));
        add(typeLabel, gbc);

        gbc.gridy++;

        if (importType == SHOEBOX) {
            fieldSpecButton = new JButton(ElanLocale.getString(
                        "ImportDialog.Button.FieldSpec"));
            fieldSpecButton.addActionListener(this);
            fieldSpecButton.setEnabled(false);
            add(fieldSpecButton, gbc);
        }

        gbc.gridy++;

        //       add(new JLabel(ElanLocale.getString("ImportDialog.Label.Media")), gbc);
        gbc.gridy = 0;
        gbc.gridx = 2;
        gbc.weightx = 1.0;
        add(sbxField, gbc);
        gbc.gridy++;
        add(typField, gbc);
        gbc.gridy++;

        //       gbc.gridy++;
        //       add(auField, gbc);
        gbc.gridy = 0;
        gbc.gridx = 3;
        gbc.weightx = 0.0;
        gbc.fill = GridBagConstraints.NONE;

        txtButton = new JButton("...");
        txtButton.addActionListener(this);

        typButton = new JButton("...");
        typButton.addActionListener(this);

        //       medButton = new JButton("...");
        //       medButton.addActionListener(this);
        add(txtButton, gbc);
        gbc.gridy++;
        add(typButton, gbc);

        gbc.gridy++;

        //       gbc.gridy++;
        //       add(medButton, gbc);
        if (importType == SHOEBOX) {
            intervalLabel = new JLabel(ElanLocale.getString(
                        "ImportDialog.Label.BlockDuration"));
            intervalField = new JTextField();

            if (Preferences.get(INTERVAL_PREF, null) != null) {
                Integer val = (Integer) Preferences.get(INTERVAL_PREF, null);
                intervalField.setText("" + val.intValue());
            } else {
                intervalField.setText("" +
                    ShoeboxPreferences.DEFAULT_BLOCK_DURATION);
            }

            GridBagConstraints gridBagConstraints = new GridBagConstraints();
            gridBagConstraints.gridx = 1;
            gridBagConstraints.gridy = 3;
            gridBagConstraints.insets = gbc.insets;
            gridBagConstraints.anchor = GridBagConstraints.WEST;
            add(intervalLabel, gridBagConstraints);

            gridBagConstraints.gridx = 2;
            gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
            gridBagConstraints.weightx = 1.0;
            add(intervalField, gridBagConstraints);
            gbc.gridy = gridBagConstraints.gridy + 1;
        }

        // ok - cancel buttons //
        JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 6, 2));
        okButton = new JButton(ElanLocale.getString("Button.OK"));
        okButton.addActionListener(this);

        cancelButton = new JButton(ElanLocale.getString("Button.Cancel"));
        cancelButton.addActionListener(this);

        buttonPanel.add(okButton);
        buttonPanel.add(cancelButton);

        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.anchor = GridBagConstraints.SOUTH;
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 0;
        gbc.gridy++;
        add(buttonPanel, gbc);

        //      auField.setEnabled(false);
        //      if (ShoeboxTypFile.getTypFileName() != "") {
        //      	typField.setText(ShoeboxTypFile.getTypFileName());
        //      }
        setShoeboxMarkerRB();

        typeRB.addItemListener(this);
        specRB.addItemListener(this);
    }

    private void setShoeboxMarkerRB() {
        if ((ShoeboxTypFile.getMarkers() != null) &&
                (ShoeboxTypFile.getMarkers().size() > 0)) {
            specRB.setSelected(true);
            typButton.setEnabled(false);
            fieldSpecButton.setEnabled(true);
        } else if ((ShoeboxTypFile.getTypFileName() != null) &&
                !ShoeboxTypFile.getTypFileName().equals("")) {
            typeRB.setSelected(true);
            typField.setText(ShoeboxTypFile.getTypFileName());
            typButton.setEnabled(true);
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public static Object showDialog() {
        return showDialog(SHOEBOX);
    }

    /**
     * DOCUMENT ME!
     *
     * @param type DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public static Object showDialog(int type) {
        return showDialog(null, type);
    }

    /**
     * Creates a Dialog to select some files for import.
     *
     * @param parent the parent Frame, can be null
     * @param type the type of import, either WAC or Shoebox
     *
     * @return a Hashtable with file names, or null
     */
    public static Object showDialog(Frame parent, int type) {
        ImportShoeboxWAC pane = new ImportShoeboxWAC(type);
        JDialog dialog = pane.createDialog(parent, type);
        dialog.show();
        dialog.dispose();

        Object o = pane.getValue();

        //System.out.println("Return Value: " + o);
        return o;
    }

    /**
     * Creates the dialog with <code>this</code> as content pane.
     *
     * @param parent the parent Frame or null
     * @param type the type of import, either WAC or Shoebox
     *
     * @return a modal JDialog
     */
    private JDialog createDialog(Frame parent, int type) {
        final JDialog dialog = new JDialog();

        if (type == WAC) {
            dialog.setTitle(ElanLocale.getString("ImportDialog.Title.WAC"));
        } else {
            dialog.setTitle(ElanLocale.getString("ImportDialog.Title.Shoebox"));
        }

        dialog.getContentPane().setLayout(new BorderLayout());
        dialog.getContentPane().add(this, BorderLayout.CENTER);
        dialog.setModal(true);
        dialog.pack();

        if (parent != null) {
            dialog.setLocationRelativeTo(parent);
        }

        dialog.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent we) {
                    setValue(null);
                }
            });

        // use the java.beans PropertyChangeSupport mechanism
        addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent event) {
                    if (dialog.isVisible() &&
                            (event.getSource() == ImportShoeboxWAC.this) &&
                            event.getPropertyName().equals(VALUE_PROPERTY)) {
                        dialog.setVisible(false);
                    }
                }
            });

        return dialog;
    }

    /**
     * DOCUMENT ME!
     *
     * @param e DOCUMENT ME!
     */
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();

        if (source == txtButton) {
            chooseSbxWAC();
        } else if (source == typButton) {
            chooseTyp();
        } else if (source == fieldSpecButton) {
            specifyFieldSpecs();

            //    }
            //      else if (source == medButton) {
            //          chooseMedia();
        } else if (source == okButton) {
            if (checkFields()) {
                setValue(fileNames);
            }
        } else if (source == cancelButton) {
            setValue(null);
        }
    }

    private void chooseSbxWAC() {
        String lastUsedDir = (String) Preferences.get("LastUsedShoeboxDir", null);

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

        JFileChooser chooser = new JFileChooser(lastUsedDir);
        chooser.setDialogTitle(ElanLocale.getString("ImportDialog.Title.Select"));

        if (importType == WAC) {
            chooser.setFileFilter(ElanFileFilter.createFileFilter(
                    ElanFileFilter.WAC_TYPE));
        } else {
            chooser.setFileFilter(ElanFileFilter.createFileFilter(
                    ElanFileFilter.SHOEBOX_TEXT_TYPE));
        }

        chooser.setApproveButtonText(ElanLocale.getString(
                "ImportDialog.Approve"));
        chooser.setDialogType(JFileChooser.OPEN_DIALOG);

        int option = chooser.showDialog(this, null);

        if (option == JFileChooser.APPROVE_OPTION) {
            File curDir = chooser.getCurrentDirectory();

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

            File f = chooser.getSelectedFile();

            if (f != null) {
                sbxField.setText(f.getAbsolutePath());
            }
        }
    }

    private void chooseTyp() {
        String lastUsedDir = (String) Preferences.get("LastUsedShoeboxTypDir",
                null);

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

        JFileChooser chooser = new JFileChooser(lastUsedDir);
        chooser.setDialogTitle(ElanLocale.getString("ImportDialog.Title.Select"));
        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                ElanFileFilter.SHOEBOX_TYP_TYPE));
        chooser.setApproveButtonText(ElanLocale.getString(
                "ImportDialog.Approve"));
        chooser.setDialogType(JFileChooser.OPEN_DIALOG);

        int option = chooser.showDialog(this, null);

        if (option == JFileChooser.APPROVE_OPTION) {
            File curDir = chooser.getCurrentDirectory();

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

            File f = chooser.getSelectedFile();

            if (f != null) {
                typField.setText(f.getAbsolutePath());
                ShoeboxTypFile.setTypFileName(f.getAbsolutePath());
            }
        }
    }

    private void specifyFieldSpecs() {
        //		JFrame frame = ELANCommandFactory.getRootFrame(transcription);
        ShoeboxTypFile.setTypFileName("");
        new ShoeboxMarkerDialog(null, true).setVisible(true);
    }

    /**
     * Checks the contents of all input fields and next the existence of the
     * designated files.
     *
     * @return true if the files exist, false otherwise
     */
    private boolean checkFields() {
        if ((sbxField.getText() == null) || (sbxField.getText().length() == 0)) {
            if (importType == WAC) {
                showError(ElanLocale.getString(
                        "ImportDialog.Message.SpecifyWAC"));
            } else {
                showError(ElanLocale.getString(
                        "ImportDialog.Message.SpecifyShoebox"));
            }

            return false;
        }

        if (typeRB.isSelected() &&
                ((typField.getText() == null) ||
                (typField.getText().length() == 0))) {
            showError(ElanLocale.getString("ImportDialog.Message.SpecifyType"));

            return false;
        }

        if (!(new File(sbxField.getText()).exists())) {
            if (importType == WAC) {
                showError(ElanLocale.getString("ImportDialog.Message.NoWAC"));
            } else {
                showError(ElanLocale.getString("ImportDialog.Message.NoShoebox"));
            }

            return false;
        } else {
            fileNames.put(TEXT_KEY, sbxField.getText());
        }

        if (typeRB.isSelected()) {
            if (!(new File(typField.getText()).exists())) {
                showError(ElanLocale.getString("ImportDialog.Message.NoType"));

                return false;
            } else {
                fileNames.put(TYPE_KEY, typField.getText());
                ShoeboxTypFile.setTypFileName(typField.getText());
            }
        } else { // specify field names is selected
            fileNames.put(TYPE_KEY, "");
            ShoeboxTypFile.setTypFileName("");
        }

        if (intervalField != null) {
            String dur = intervalField.getText();
            int durVal = ShoeboxPreferences.DEFAULT_BLOCK_DURATION;

            try {
                durVal = Integer.parseInt(dur);
                ShoeboxPreferences.preferredBlockDuration = durVal;
                Preferences.set(INTERVAL_PREF, durVal, null);
            } catch (NumberFormatException nfe) {
                // ignore
            }
        }

        return true;
    }

    /**
     * Shows an error dialog.
     *
     * @param message
     */
    private void showError(String message) {
        JOptionPane.showMessageDialog(this, message,
            ElanLocale.getString("Message.Error"), JOptionPane.ERROR_MESSAGE);
    }

    /**
     * DOCUMENT ME!
     *
     * @return the user object or null
     */
    public Object getValue() {
        return value;
    }

    /**
     * Sets the new value the user has chosen.
     *
     * @param newValue the new value
     */
    public void setValue(Object newValue) {
        Object oldValue = value;
        value = newValue;
        firePropertyChange(VALUE_PROPERTY, oldValue, value);
    }

    public void itemStateChanged(ItemEvent e) {
        if ((e.getSource() == typeRB) &&
                (e.getStateChange() == ItemEvent.SELECTED)) {
            typeLabel.setEnabled(true);
            typButton.setEnabled(true);
            typField.setEnabled(true);

            fieldSpecButton.setEnabled(false);

            if ((typField.getText() == null) ||
                    (typField.getText().length() == 0)) {
                typButton.doClick(200);
            }
        } else if ((e.getSource() == specRB) &&
                (e.getStateChange() == ItemEvent.SELECTED)) {
            typeLabel.setEnabled(false);
            typButton.setEnabled(false);
            typField.setEnabled(false);

            fieldSpecButton.setEnabled(true);
            fieldSpecButton.doClick(200);
        }
    }
}
