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.net.URL;
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.iris.Fissures.IfNetwork.ChannelId;
import edu.iris.Fissures.network.ChannelIdUtil;
import edu.sc.seis.fissuresUtil.cache.AbstractJob;
import edu.sc.seis.fissuresUtil.cache.EventUtil;
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.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.xml.DataSetSeismogram;
import edu.sc.seis.fissuresUtil.xml.StdAuxillaryDataNames;
import edu.sc.seis.fissuresUtil.xml.URLDataSetSeismogram;
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;

/**
 * @author oliverpa Created on Feb 15, 2005
 */
public class ApprovalExportTask extends DataSetCrawler implements Task {

    /**
     *
     */
    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("ApprovalExportTask must have a DataSetBrowser associated with it");
        }
        if(params.containsKey("PromptIfNoOpenDataSets")) {
            String promptString = (String)params.get("PromptIfNoOpenDataSets");
            setPromptIfNoOpenDataSets(Boolean.valueOf(promptString).booleanValue());
        }
    }

    /**
     *
     */
    public void invoke() throws Exception {
        currentCrawlAction = new InitialCrawlAction();
        boolean doneSomething = crawlDataSets();
        if(seisCount > 0) {
            optionsDialogue.setVisible(true);
        } else if(doneSomething) {
            JOptionPane.showMessageDialog(FrameManager.getManager()
                                                  .getCurrentFrame(),
                                          "No quality control data were found in current dataset.",
                                          "No quality control data",
                                          JOptionPane.INFORMATION_MESSAGE);
        }
    }

    /**
     *
     */
    public void destroy() {
    // TODO Auto-generated method stub
    }

    /**
     *
     */
    public void crawlAction(DataSetSeismogram seis) {
        currentCrawlAction.doCrawlAction(seis);
    }

    public void createFileGUI() throws ConfigurationException {
        final JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        String defName = null;
        String extensions[] = new String[1];
        if (copyScript){
            extensions[0] = "sh";
            defName = "qc_copy.sh";
        } else {
            extensions[0] = "txt";
            defName = "quality_control.txt";
        }
        fc.setSelectedFile(new File(defName));
        fc.setFileFilter(new FileNameFilter(extensions));
        fc.setDialogTitle("Save Quality Control Data");
        int returnVal = fc.showSaveDialog(FrameManager.getManager()
                .getCurrentFrame());
        if(returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            ApprovalSaver saver;
            if(copyScript) {
                createCopyScript();
                saver = new ApprovalSaver(textTable.toString("\t"), file);
                
            } else {
                createTextTable();
                if(tabDelimited) {
                    saver = new ApprovalSaver(textTable.toString("\t"), file);
                } else {
                    saver = new ApprovalSaver(textTable.toString(), file);
                }
            }
            JobTracker.getTracker().add(saver);
            WorkerThreadPool.getDefaultPool().invokeLater(saver);
        } else {
            //log.append("Open command cancelled by user.");
        }
    }

    private void createTextTable() {
        textTable = new TextTable(template.length, true);
        textTable.addRow(template, true);
        currentCrawlAction = new TextTableCrawlAction();
        crawlDataSets();
    }

    private void createCopyScript() {
        textTable = new TextTable(1, false);
        textTable.addRow("#!/bin/sh");
        currentCrawlAction = new CopyScriptCrawlAction();
        crawlDataSets();
    }

    private interface CrawlAction {

        public void doCrawlAction(DataSetSeismogram seis);
    }

    private class InitialCrawlAction implements CrawlAction {

        public void doCrawlAction(DataSetSeismogram seis) {
            EventAccessOperations event = seis.getDataSet().getEvent();
            ChannelId chanId = seis.getRequestFilter().channel_id;
            String approved = (String)seis.getAuxillaryData(StdAuxillaryDataNames.APPROVED);
            if(approved != null) {
                seisCount++;
            }
        }
    }

    private class TextTableCrawlAction implements CrawlAction {

        public void doCrawlAction(DataSetSeismogram seis) {
            EventAccessOperations event = seis.getDataSet().getEvent();
            ChannelId chanId = seis.getRequestFilter().channel_id;
            String approved = (String)seis.getAuxillaryData(StdAuxillaryDataNames.APPROVED);
            if(approved != null) {
                textTable.addRow(new String[] {EventUtil.getEventInfo(event),
                                               ChannelIdUtil.toString(chanId),
                                               approved});
            }
        }
    }

    private class CopyScriptCrawlAction implements CrawlAction {
        
        File previousDirectory;

        public void doCrawlAction(DataSetSeismogram seis) {
            URLDataSetSeismogram urlDSS = (URLDataSetSeismogram)seis;
            URL[] urls = urlDSS.getURLs();
            String approved = (String)seis.getAuxillaryData(StdAuxillaryDataNames.APPROVED);
            for(int i = 0; i < urls.length; i++) {
                File seisFile = new File(urls[i].getFile());
                File currentDirectory = new File(urls[i].getFile()).getParentFile();
                if (!currentDirectory.equals(previousDirectory)){
                    textTable.addRow("cd " + currentDirectory.getParentFile());
                    textTable.addRow("mkdir -p good/" + currentDirectory.getName());
                    textTable.addRow("mkdir -p bad/" + currentDirectory.getName());
                    previousDirectory = currentDirectory;
                }
                if (Boolean.valueOf(approved).booleanValue()){
                    textTable.addRow("cp " + seisFile + " good/" + currentDirectory.getName() + "/" + seisFile.getName());
                } else {
                    textTable.addRow("cp " + seisFile + " bad/" + currentDirectory.getName() + "/" + seisFile.getName());
                }
            }
        }
    }

    private class ApprovalOptionsDialogue 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 JRadioButton copyScriptButton = new JRadioButton("UNIX Copy Script");

        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 ApprovalOptionsDialogue() {
            super("Set Text Formatting");
            getContentPane().setLayout(new BorderLayout());
            buttonGroup.add(tabDelimButton);
            buttonGroup.add(spaceFilledButton);
            buttonGroup.add(copyScriptButton);
            radioButtonPanel.setBorder(groupBorder);
            radioButtonPanel.add(tabDelimButton);
            radioButtonPanel.add(spaceFilledButton);
            radioButtonPanel.add(copyScriptButton);
            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()) {
                    System.out.println("tabDelimButton.isSelected()");
                    tabDelimited = true;
                    copyScript = false;
                } else if(spaceFilledButton.isSelected()) {
                    System.out.println("spaceFilledButton.isSelected()");
                    tabDelimited = false;
                    copyScript = false;
                } else {
                    System.out.println("else");
                    tabDelimited = false;
                    copyScript = true;
                }
                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 ApprovalSaver extends AbstractJob {

        ApprovalSaver(String data, File file) {
            super("Save quality control data");
            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 quality control data.",
                                              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;
    }

    private static final String[] template = new String[] {"Event",
                                                           "Station",
                                                           "Approved"};

    private int seisCount = 0;

    private CrawlAction currentCrawlAction = new TextTableCrawlAction();

    private TaskAction dsbAction;

    private DataSetBrowser dataSetBrowser;

    private TextTable textTable = new TextTable(template.length, true);

    private boolean tabDelimited = true;

    private boolean copyScript = false;

    private ApprovalOptionsDialogue optionsDialogue = new ApprovalOptionsDialogue();
}