/**
 * FlagExportTask.java
 *
 * @author Created by Omnicore CodeGuide
 */

package edu.sc.seis.gee.task;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.Border;
import edu.iris.Fissures.IfEvent.EventAccessOperations;
import edu.sc.seis.fissuresUtil.cache.AbstractJob;
import edu.sc.seis.fissuresUtil.cache.JobTracker;
import edu.sc.seis.fissuresUtil.cache.WorkerThreadPool;
import edu.sc.seis.fissuresUtil.chooser.FileNameFilter;
import edu.sc.seis.fissuresUtil.display.TextTable;
import edu.sc.seis.fissuresUtil.display.drawable.Flag;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.xml.DataSetSeismogram;
import edu.sc.seis.gee.CommonAccess;
import edu.sc.seis.gee.FrameManager;
import edu.sc.seis.gee.configurator.ConfigurationException;
import edu.sc.seis.gee.task.dataSetBrowser.DataSetBrowser;



public class FlagExportTask extends DataSetCrawler implements Task{

    private static final String[] template =
        new String[]{Flag.NAME, Flag.ORIGIN_DIFF, Flag.TAUP_P, Flag.TIME_DIFF_ORIG_P,
            Flag.DISTANCE_FROM_ORIG, Flag.BACK_AZIMUTH, Flag.CHANNEL,
            Flag.EVENT_NAME, Flag.EVENT_LAT, Flag.EVENT_LON, Flag.EVENT_DEPTH,
            Flag.EVENT_MAG, Flag.EVENT_ORIG, Flag.TIME};
    private TaskAction dsbAction;
    private DataSetBrowser dataSetBrowser;
    private TextTable textTable = new TextTable(Flag.getFlagDataHeader(template).length, true);
    private boolean tabDelimited = true;
    private PickOptionsDialogue optionsDialogue = new PickOptionsDialogue();

    /**
     * Configures a <code>Task</code> with any needed parameters. The Task
     * should have default values for as many things as possible, but can
     * throw a ConfigureException if a required parameter is missing.
     *
     * @param params a <code>Map</code> value
     * @exception ConfigurationException if an error occurs
     */
    public void configure(Map params) throws ConfigurationException {
        if (params.containsKey("DataSetBrowser")){
            String displayId = (String)params.get("DataSetBrowser");
            dsbAction =
                CommonAccess.getCommonAccess().getTaskAction(displayId);
            initCrawler(dsbAction);
            dataSetBrowser = (DataSetBrowser)dsbAction.getTask();
        }
        else{
            throw new ConfigurationException("FlagExportTask must have a DataSetBrowser associated with it");
        }
        textTable.addRow(Flag.getFlagDataHeader(template), true);
    }

    /**
     * Called when a task is to be executed, usually by a menu or toolbar
     * selection for simple tasks.
     *
     *
     * @exception Exception if an error occurs
     */
    public void invoke() throws Exception {
        textTable.clear();
        boolean doneSomething = crawlDataSets();
        if (textTable.numRows() > 0){
            optionsDialogue.setVisible(true);
        }
        else if (doneSomething){
            JOptionPane.showMessageDialog(FrameManager.getManager().getCurrentFrame(),
                                          "No picks were found in current dataset.",
                                          "No Picks",
                                          JOptionPane.INFORMATION_MESSAGE);
        }
    }

    /**
     * Called when reset is invoked on gee or if this task is no longer being used
     *
     */
    public void destroy() {
        // TODO
    }

    public void crawlAction(DataSetSeismogram seis){
        EventAccessOperations event = seis.getDataSet().getEvent();
        textTable.join(Flag.getFlagData(seis, event, template));
    }

    public void createFileGUI() throws ConfigurationException {

        final JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        String extensions[] = new String[1];
        extensions[0] = "txt";
        fc.setFileFilter(new FileNameFilter(extensions));

        fc.setDialogTitle("Save Pick Flag Data");
        String defName = "picks.txt";
        fc.setSelectedFile(new File(defName));

        int returnVal = fc.showSaveDialog(FrameManager.getManager().getCurrentFrame());

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();


            PickSaver saver;
            if (tabDelimited){
                saver = new PickSaver(textTable.toString("\t"), file);
            }
            else{
                saver = new PickSaver(textTable.toString(), file);
            }
            JobTracker.getTracker().add(saver);
            WorkerThreadPool.getDefaultPool().invokeLater(saver);
        } else {
            //log.append("Open command cancelled by user.");
        }
    }

    private class PickOptionsDialogue extends JFrame{

        private JPanel radioButtonPanel = new JPanel();
        private JPanel controlButtonPanel = new JPanel();
        private JRadioButton tabDelimButton = new JRadioButton("Tab Delimited");
        private JRadioButton spaceFilledButton = new JRadioButton("Formatted Table");
        private ButtonGroup buttonGroup = new ButtonGroup();
        private Border groupBorder = BorderFactory.createTitledBorder("Text Output");
        private JButton okButton = new JButton("OK");
        private JButton cancelButton = new JButton("Cancel");

        public PickOptionsDialogue(){
            super("Set Text Formatting");
            getContentPane().setLayout(new BorderLayout());

            buttonGroup.add(tabDelimButton);
            buttonGroup.add(spaceFilledButton);
            radioButtonPanel.setBorder(groupBorder);
            radioButtonPanel.add(tabDelimButton);
            radioButtonPanel.add(spaceFilledButton);
            getContentPane().add(radioButtonPanel, BorderLayout.NORTH);

            okButton.addActionListener(new ActionListener(){
                        public void actionPerformed(ActionEvent e) {
                            doOKAction();
                        }
                    });
            cancelButton.addActionListener(new ActionListener(){
                        public void actionPerformed(ActionEvent e){
                            doCancelAction();
                        }
                    });
            controlButtonPanel.add(okButton);
            controlButtonPanel.add(cancelButton);

            tabDelimButton.setSelected(true);
            okButton.setSelected(true);

            getContentPane().add(radioButtonPanel, BorderLayout.NORTH);
            getContentPane().add(controlButtonPanel, BorderLayout.SOUTH);
            pack();
        }

        private void doOKAction(){
            try {
                if (tabDelimButton.isSelected()){
                    tabDelimited = true;
                }
                else {
                    tabDelimited = false;
                }
                setVisible(false);
                createFileGUI();
            } catch (ConfigurationException e) {
                GlobalExceptionHandler.handle(e);
            }
        }

        private void doCancelAction(){
            setVisible(false);
        }

        public void setVisible(boolean b){
            this.setLocationRelativeTo(FrameManager.getManager().getCurrentMainFrame());
            super.setVisible(b);
        }
    }

    class PickSaver extends AbstractJob {

        PickSaver(String data, File file){
            super("Save pick flags");
            this.file = file;
            this.data = data;
        }

        public void runJob(){
            FileWriter writer = null;
            try{
                writer = new FileWriter(file);
                writer.write(data);
            } catch(Throwable e){
                GlobalExceptionHandler.handle("problem saving pick flags.", e);
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (IOException e) {
                        // oh well
                        GlobalExceptionHandler.handle("unable to close the file.", e);
                    }
                }
                setFinished();
            }
        }

        File file;
        String data;
    }

}


