/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package usda.weru.weps.location.mode;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.util.Iterator;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import usda.weru.util.LoadingContext;
import usda.weru.util.PropertyVetoRunnableException;
import usda.weru.weps.RunFileBean;
import usda.weru.weps.RunFileBean.StationType;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.chooser.StationChooser;
import usda.weru.weps.location.mode.ChoiceHandler.ChoiceBeanState;

/**
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class ChoiceHandler extends AbstractStationModeHandler<ChoiceBeanState> {

    /**
     *
     * @param chooser
     */
    @Override
    protected void setView(StationChooser chooser) {
        chooser.setView(StationChooser.View.Choice);
    }

    /**
     *
     * @param state
     */
    protected void handleLatLongChange(ChoiceBeanState state) {
        //Get the valid choices                
        validateSelectedStation(state);
    }

    @Override
    protected void handleValidate(final ChoiceBeanState state, Station oldStation, final Station newStation,
            boolean loading, PropertyChangeEvent event) throws PropertyVetoException {
        if (!loading) {
            //don't care if we're not loading
            return;
        }
        if (newStation == null) {
            //null is okay
            return;
        }
        //the newStation must be in the list of valid stations.  Otherwise we set to the nearest station        
        Station[] validChoices = getValidStationChoices(state);
        for (Station validChoice : validChoices) {
            if (newStation.equals(validChoice)) {
                return;
            }
        }

        //not valid, we need to change to the nearest station
        final Station newChoice = (validChoices != null && validChoices.length > 0) ? validChoices[0] : null;

        //send the exception off 
        throw new PropertyVetoRunnableException("Station choice is no longer valid.", event, new Runnable() {

            @Override
            public void run() {

                JOptionPane pane = new JOptionPane("The simulation you are attempting to open uses a "
                        + state.getType().getDisplayName() + " station that is no longer a valid selection. "
                        + newStation.getDisplayName() + " will be substituted with the nearest station. "
                        + "Simulation results may be different.", JOptionPane.WARNING_MESSAGE) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public int getMaxCharactersPerLineCount() {
                        return 80;
                    }
                };

                JDialog dialog = pane.createDialog(state.getType().getDisplayName() + " Station Selection");
                dialog.setModal(true);
                dialog.setVisible(true);

                //set to a valid station choice
                state.setSelectedStation(newChoice);
            }
        });

    }

    /**
     *
     * @param chooser
     * @param toValidate
     * @return station that should be the current selection or null
     */
    private void validateSelectedStation(AbstractStationModeHandler<?>.BeanState state) {

        //the results are cached for quick responses, likely was already executed by the view's update
        Station[] stations = getValidStationChoices(state);

        proxy(state, stations);

    }

    /**
     *
     * @param state
     * @param choices
     */
    protected static void proxy(usda.weru.weps.location.mode.AbstractStationModeHandler<?>.BeanState state, Station[] choices) {

        //loop over every StationChooser tied to this state
        Iterator<StationChooser> i = state.choosers();
        while (i.hasNext()) {
            StationChooser chooser = i.next();

            chooser.setStationChoices(choices);
            chooser.setDistance(state.getDistanceLimit());
        }

        //do not select the nearest station if we're in loading mode
        if (!LoadingContext.isLoading()) {
            Station nearest = choices.length > 0 ? choices[0] : null;
            state.setSelectedStation(nearest);
        }
    }

    /**
     *
     * @param state
     * @return
     */
    protected Station[] getValidStationChoices(AbstractStationModeHandler<?>.BeanState state) {
        //return the stations from the data model
        return state.getDataModel().getNearestStations(state.getBean().getLatLong(), state.getDistanceLimit(), -1);
    }

    @Override
    @Deprecated
    public int getId() {
        return 0;
    }

    /**
     *
     * @return
     */
    @Override
    public String getDisplayName() {
        return "Station Choice List";
    }

    @Override
    public String getName() {
        return "choice";
    }

    /**
     *
     * @param bean
     * @param type
     * @return
     */
    @Override
    protected ChoiceBeanState createBeanState(RunFileBean bean, StationType type) {
        return new ChoiceBeanState(bean, type);
    }

    /**
     *
     */
    protected class ChoiceBeanState extends AbstractStationModeHandler<?>.BeanState implements PropertyChangeListener {

        /**
         *
         * @param bean
         * @param type
         */
        public ChoiceBeanState(RunFileBean bean, RunFileBean.StationType type) {
            super(bean, type);
        }

        /**
         *
         */
        @Override
        public void install() {
            super.install();
            handleLatLongChange(this);
            getBean().addPropertyChangeListener(RunFileBean.PROP_LATLONG, this);
        }

        /**
         *
         */
        @Override
        public void uninstall() {
            super.uninstall();
            getBean().removePropertyChangeListener(RunFileBean.PROP_LATLONG, this);
        }

        /**
         *
         * @param evt
         */
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
/**
                 * Note:  Assertions are not enabled.  These will be useless items
                 * unless assertions are enabled.  Thus, they will be commented out unless
                 * the user wishes to enable specific assertions (feed the virtual machine 
                 * the -ea argument).
                 */
//            assert getBean() == evt.getSource() : "BeanState getting events from unexpected source.";
            if (RunFileBean.PROP_LATLONG.equals(evt.getPropertyName())) {
                //lat long changed
                handleLatLongChange(this);
            }
        }
    }
}
