package edu.sc.seis.gee.task;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.xml.parsers.ParserConfigurationException;
import edu.iris.Fissures.AuditInfo;
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.dataset.Organizer;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.xml.DataSet;
import edu.sc.seis.fissuresUtil.xml.DataSetToXML;
import edu.sc.seis.fissuresUtil.xml.IncomprehensibleDSMLException;
import edu.sc.seis.fissuresUtil.xml.UnsupportedFileTypeException;
import edu.sc.seis.gee.CommonAccess;
import edu.sc.seis.gee.FrameManager;
import edu.sc.seis.gee.NetworkGateKeeper;
import edu.sc.seis.gee.NoNetworkException;
import edu.sc.seis.gee.configurator.ConfigurationException;
import edu.sc.seis.gee.task.dataSetBrowser.DataSetBrowser;

/**
 * LoadDataSetTask takes a taskconfig item in the params called
 * "automaticAction" if it is set to "none", the loaded data set is only in the
 * data set editor and is not displayed. This is also what happens if
 * automaticAction is not set If it is set to "load into display" then when the
 * data set is loaded, the traces it has are put into a seismogram display. If
 * it is set to "load into display and bring to front" the display is also given
 * focus.
 * 
 * Created: Fri Jan 18 15:41:26 2002
 * 
 * @author <a href="mailto:">Srinivasa Telukutla </a>
 * @version $Id: LoadDataSetTask.java 19019 2007-04-29 23:50:16Z crotwell $
 */
public class LoadDataSetTask extends JPanel implements Task {

    public void invoke() throws ConfigurationException, NoNetworkException {
        String respondId = (String)params.get("do_file_input");
        if(respondId != null && respondId.equals("true")) {
            showFileGUI();
        } else if((respondId = (String)params.get("do_url_directory")) != null) {
            try {
                loadDataSet(new URL(respondId));
            } catch(MalformedURLException e) {
                throw new ConfigurationException("URL is malformed, "
                        + respondId, e);
            } // end of try-catch
        } else if((respondId = (String)params.get("do_jar_file")) != null) {
            loadClassic(respondId);
        } else if((respondId = (String)params.get("do_url_input")) != null) {
            showURLInputGUI();
        } else {
            throw new ConfigurationException("One of do_file_input, do_url_directory, do_jar_file or do_url_input must be defined");
        } // end of else
        if(params.containsKey("automaticAction")) {
            String autoAction = (String)params.get("automaticAction");
            if(autoAction.equals("none")) {
                loadIntoDisplay = false;
                bringToFront = false;
            } else if(autoAction.equals("load into display")) {
                loadIntoDisplay = true;
                bringToFront = false;
            } else if(autoAction.equals("load into display and bring to front")) {
                loadIntoDisplay = true;
                bringToFront = true;
            }
        }
    }

    private boolean loadIntoDisplay = false;

    private boolean bringToFront = false;

    public void destroy() {}

    public void loadDataSet(URL url) throws NoNetworkException {
        checkForNetUsage(url);
        WorkerThreadPool.getDefaultPool().invokeLater(new DataSetLoader(url));
    }

    private void checkForNetUsage(final URL url) throws NoNetworkException {
        if(!(url.getProtocol().equalsIgnoreCase("file")
                || url.getProtocol().equalsIgnoreCase("jar") || url.getProtocol()
                .equalsIgnoreCase("jar:file"))
                && !NetworkGateKeeper.accessAllowed()) {
            throw new NoNetworkException();
        }
    }

    private class DataSetLoader extends AbstractJob {

        public DataSetLoader(URL url) {
            super("Data Set Loader");
            this.url = url;
            JobTracker.getTracker().add(this);
        }

        public void runJob() {
            try {
                loadDataSet(url);
            } catch(Exception ex) {
                GlobalExceptionHandler.handle("A problem occurred while trying to load a DataSet",
                                              ex);
            }
        }

        boolean placeholderDS = true;

        protected void loadDataSet(URL dsURL) throws NoNetworkException,
                ConfigurationException {
            checkForNetUsage(dsURL);
            setStatus("Converting DataSet to XML");
            try {
                DataSet ds = DataSetToXML.load(dsURL);
                Organizer organizer = CommonAccess.getCommonAccess()
                        .getOrganizer();
                setStatus("Setting audit info");
                AuditInfo[] audit_info = new AuditInfo[1];
                audit_info[0] = new AuditInfo(System.getProperty("user.name"),
                                              "loaded from " + dsURL.toString());
                setStatus("Adding to organizer");
                organizer.addDataSet(ds, audit_info);
                if(params.containsKey("DataSetBrowser")) {
                    TaskAction dsbAction = CommonAccess.getCommonAccess()
                            .getTaskAction((String)params.get("DataSetBrowser"));
                    DataSetBrowser dsb = (DataSetBrowser)dsbAction.getTask();
                    dsb.invoke();
                    dsbAction.checkDisplayLocation();
                    dsb.expandLastRow();
                }
                if(loadIntoDisplay) {
                    String[] names = ds.getDataSetSeismogramNames();
                    for(int i = 0; i < names.length; i++) {
                        LoadSacFile.addToDisplay(ds.getDataSetSeismogram(names[i]),
                                                 bringToFront);
                    }
                }
            } catch(IncomprehensibleDSMLException sax) {
                JOptionPane.showMessageDialog(null,
                                              "We had trouble loading the dataset you specified("
                                                      + dsURL
                                                      + ").\n\n"
                                                      + "The URL must specify a valid DSML file, not a directory or other data\n"
                                                      + "file.  DMSL files normally end in \".dsml\".  Please check and retry.",
                                              "Unable to load dataset",
                                              JOptionPane.WARNING_MESSAGE);
                logger.debug("We had trouble loading the dataset you specified("
                                     + dsURL + ")",
                             sax);
            } catch(IOException io) {
                JOptionPane.showMessageDialog(null,
                                              "We had trouble reading the dataset you specified("
                                                      + dsURL + ").\n",
                                              "Unable to load dataset",
                                              JOptionPane.WARNING_MESSAGE);
                logger.debug("We had trouble reading the dataset you specified("
                                     + dsURL + ").",
                             io);
            } catch(ParserConfigurationException parser) {
                GlobalExceptionHandler.handle("XML parser misconfigured",
                                              parser);
            } catch(UnsupportedFileTypeException unsup) {
                GlobalExceptionHandler.handle("Unsupported file type at URL "
                        + dsURL, unsup);
            }
            setFinished();
        }

        private URL url;
    }

    private void showURLInputGUI() {
        if(!NetworkGateKeeper.accessAllowed()) {
            JOptionPane.showMessageDialog(FrameManager.getManager()
                                                  .getCurrentMainPanel(),
                                          "GEE is unable to get to the network to load a URL",
                                          "Network unavailable!",
                                          JOptionPane.WARNING_MESSAGE);
            return;
        }
        String value = (String)JOptionPane.showInputDialog(FrameManager.getManager()
                                                                   .getCurrentMainPanel(),
                                                           "Select a URL to load",
                                                           "Load a DataSet from a URL",
                                                           JOptionPane.QUESTION_MESSAGE,
                                                           null,
                                                           null,
                                                           "http://");
        if(value == null) {
            return;
        }
        try {
            loadDataSet(new URL(value));
        } catch(NoNetworkException e) {
            GlobalExceptionHandler.handle(e);
        } catch(MalformedURLException ex) {
            JOptionPane.showMessageDialog(FrameManager.getManager()
                                                  .getCurrentMainPanel(),
                                          value
                                                  + " doesn't appear to be a valid URL.  Try navigating to the DataSet file in your browser, copying the location, and pasting it into the dialog",
                                          "Invalid URL",
                                          JOptionPane.WARNING_MESSAGE);
            showURLInputGUI();
        }
    }

    private void showFileGUI() {
        JFileChooser jfileChooser = new JFileChooser();
        jfileChooser.setFileFilter(new FileNameFilter(new String[] {"dsml"}));
        jfileChooser.setDialogTitle("Load DataSet");
        int returnVal = jfileChooser.showOpenDialog(LoadDataSetTask.this);
        if(returnVal == JFileChooser.APPROVE_OPTION) {
            File file = jfileChooser.getSelectedFile();
            try {
                loadDataSet(file.toURL());
            } catch(NoNetworkException e) {
                // shouldn't not ever happen as this is a file: url
                GlobalExceptionHandler.handle(e);
            } catch(MalformedURLException e) {
                // can't happen???
                GlobalExceptionHandler.handle("Bad file selected.", e);
            } // end of try-catch
        }
    }

    public void configure(Map configParams) {
        this.params = configParams;
    }

    private void loadClassic(String dataSetFileName)
            throws ConfigurationException {
        String fullFileName = "edu/sc/seis/gee/classicDataSets/"
                + dataSetFileName;
        URL jarURL = (LoadDataSetTask.class).getClassLoader()
                .getResource(fullFileName);
        if(jarURL != null) {
            try {
                new DataSetLoader(jarURL).run();
            } catch(Exception e) {
                throw new ConfigurationException("Couln't load dataset from "
                        + jarURL, e);
            }
        } else {
            throw new ConfigurationException("Unable to find classic dataset for "
                    + fullFileName);
        } // end of else
    }

    private Map params;

    static org.apache.log4j.Category logger = org.apache.log4j.Category.getInstance(LoadDataSetTask.class.getName());
}// LoadDataSetTask
