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

package edu.sc.seis.gee.task;

import java.awt.BorderLayout;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.StringTokenizer;
import javax.swing.JPanel;
import edu.iris.Fissures.IfEvent.EventAccessOperations;
import edu.iris.Fissures.IfEvent.NoPreferredOrigin;
import edu.iris.Fissures.IfNetwork.Channel;
import edu.iris.Fissures.IfNetwork.Station;
import edu.iris.Fissures.network.ChannelIdUtil;
import edu.iris.Fissures.network.StationIdUtil;
import edu.sc.seis.TauP.PathPlot;
import edu.sc.seis.TauP.SphericalCoords;
import edu.sc.seis.TauP.TauModelException;
import edu.sc.seis.TauP.TauP_Path;
import edu.sc.seis.fissuresUtil.bag.TauPUtil;
import edu.sc.seis.fissuresUtil.display.BasicSeismogramDisplay;
import edu.sc.seis.fissuresUtil.display.SeismogramDisplay;
import edu.sc.seis.fissuresUtil.display.VerticalSeismogramDisplay;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.xml.DataSet;
import edu.sc.seis.fissuresUtil.xml.DataSetSeismogram;
import edu.sc.seis.gee.CommonAccess;
import edu.sc.seis.gee.configurator.ConfigurationException;

public class TauPPathTask extends JPanel implements Task {


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

    /**
     bo     * 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{}

    public void displayPath(SeismogramDisplay display){
        colSeis = display;
        if (colSeis != null) {

            HashMap stations;
            HashMap events = new HashMap();
            if(display instanceof VerticalSeismogramDisplay){
                LinkedList displays =
                    ((VerticalSeismogramDisplay)display).getDisplays();
                Iterator it = displays.iterator();
                while (it.hasNext()) {
                    BasicSeismogramDisplay currDisp =
                        ((BasicSeismogramDisplay)it.next());
                    DataSetSeismogram[] seismos = currDisp.getSeismograms();
                    for(int i = 0; i < seismos.length; i++){
                        DataSet dataset =seismos[i].getDataSet();
                        EventAccessOperations currEvent = dataset.getEvent();

                        if ( ! events.containsKey(currEvent)) {
                            events.put(currEvent, new HashMap());
                        } // end of if ( ! events.containsKey(currEvent))

                        // use HashMap so we can key off of the station id and
                        // avoid duplicates if the station objects are equivalent,
                        // but not the same object
                        stations = (HashMap)events.get(currEvent);
                        try {
                            Channel chan =
                                dataset.getChannel(seismos[i].getRequestFilter().channel_id);
                            // check for channel not in dataset
                            if ( chan != null) {
                                Station currStation = chan.getSite().getStation();
                                stations.put(StationIdUtil.toString(currStation.get_id()),
                                             currStation);

                            } else {

                            } // end of else

                        } catch (Throwable e) {
                            GlobalExceptionHandler.handle("Problem getting the station information for channel "+
                                                                               ChannelIdUtil.toString(seismos[i].getRequestFilter().channel_id),
                                                                           e);
                        } // end of try-catch

                    }
                }

                it = events.keySet().iterator();
                while (it.hasNext()) {
                    EventAccessOperations currEvent = (EventAccessOperations)it.next();
                    stations = (HashMap)events.get(currEvent);
                    Collection stationCollection = stations.values();
                    Station[] stationArray =
                        (Station[])stationCollection.toArray(new Station[0]);

                    if (currEvent != null && stationArray.length > 0){
                        try{
                            double distance = SphericalCoords.distance(currEvent.get_preferred_origin().getLocation().latitude,
                                                                       currEvent.get_preferred_origin().getLocation().longitude,
                                                                       stationArray[0].getLocation().latitude,
                                                                       stationArray[0].getLocation().longitude);
                            //tauP.calculate(distance, currEvent.get_preferred_origin().my_location.depth.value);
                            tpath.setSourceDepth(currEvent.get_preferred_origin().getLocation().depth.value);
                            //tpath.calcPath(distance);
                            tpath.calculate(distance);
                            p.removeAllElements();
                            for (int i = 0; i < tpath.getNumArrivals(); i++) {
                                p.addElement(tpath.getArrival(i));
                            }
                            p.repaint();
                        }
                        catch(NoPreferredOrigin npo){

                        }
                        catch(TauModelException tme){
                            GlobalExceptionHandler.handle(tme);
                        }
                    } // end of while (it.hasNext())
                } // end of if (colSeis != null)
            }
        }
    }

    /**
     * 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 {

        //        String taskId = (String)params.get("travelTimeCalc");
        //        TaskAction tauPTaskAction = CommonAccess.getCommonAccess().getTaskAction(taskId);
        //        TauPTask tauPTask = (TauPTask)tauPTaskAction.getTask();
        //        tauP = tauPTask.getTauP();
        //        p = tauP.pathPlotArea;
        try{
            TauPUtil ttime = CommonAccess.getCommonAccess().getTravelTimeCalc();
            tpath = new TauP_Path(ttime.getTauModel());

            if (params.containsKey("phases")){
                String phasesString = (String)params.get("phases");
                StringTokenizer phasesTok = new StringTokenizer(phasesString,",");
                int tokens = phasesTok.countTokens();
                String[] phases = new String[tokens];
                for (int i = 0; i < tokens; i++){
                    phases[i] = phasesTok.nextToken();
                }
                tpath.setPhaseNames(phases);
            }

            p = new PathPlot();
            p.setTauModel(tpath.getTauModel());
            setLayout(new BorderLayout());
            add(p, BorderLayout.CENTER);
        }
        catch(TauModelException e){
            throw new ConfigurationException("Invalid Tau model", e);
        }

    }

    private SeismogramDisplay colSeis;
    //private TauP tauP;
    private TauP_Path tpath;
    private PathPlot p;
}

