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

import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import usda.weru.util.ConfigData;
import usda.weru.util.FireAllContext;
import usda.weru.util.LoadingContext;
import usda.weru.util.PropertyVetoRunnableException;
import usda.weru.util.ReportContext;
import usda.weru.weps.RunFileBean;
import usda.weru.weps.location.chooser.StationModeChooser;

/**
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class StationModeSelectionController implements VetoableChangeListener {

    private final RunFileBean c_bean;
    private final RunFileBean.StationType c_type;

    private StationModeSelectionController(RunFileBean bean, RunFileBean.StationType type) {
        c_bean = bean;
        c_type = type;

        switch (c_type) {
            case Cligen:
                c_bean.addVetoableChangeListener(RunFileBean.PROP_CLIGEN_STATION_MODE, this);
                break;
            case Windgen:
                c_bean.addVetoableChangeListener(RunFileBean.PROP_WINDGEN_STATION_MODE, this);
                break;
        }
    }

	/**
	 *
	 * @param bean
	 */
	public static void install(RunFileBean bean) {
        install(bean, RunFileBean.StationType.Cligen);
        install(bean, RunFileBean.StationType.Windgen);
    }

	/**
	 *
	 * @param bean
	 * @param type
	 */
	public static void install(RunFileBean bean, RunFileBean.StationType type) {
        new StationModeSelectionController(bean, type);
    }

	/**
	 *
	 * @param mode
	 */
	public void setStationMode(StationMode mode) {
        switch (c_type) {
            case Cligen:
                c_bean.setCligenStationMode(mode);
                break;
            case Windgen:
                c_bean.setWindgenStationMode(mode);
                break;
        }
    }

    private void validate(final StationMode[] allowed, final StationMode oldMode, final StationMode newMode, PropertyChangeEvent event) throws PropertyVetoException {
        if (FireAllContext.isInFireAll()) {
            //we work just fine with actuall listening.  Fire alls break this
            return;
        }
        if (!LoadingContext.isLoading()) {
            //let's assume that the application is right and we only care when loading a run file.
            return;
        }
        if(ReportContext.isInReport()){
            //We don't do any checks for reports.
            return;
        }
        if (newMode == null) {
            return;
        }
        for (StationMode mode : allowed) {
            if (mode == newMode) {
                //all is well
                return;
            }
        }

        

        //not allowed, handle the different selection types
        switch (allowed.length) {
            case 0:
                //really not good, no valid modes
                throw new PropertyVetoRunnableException("There is a configuration error. No valid " + c_type.getDisplayName() + " station modes are configured.", event) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void run() {
                        JOptionPane pane = new JOptionPane("There is a configuration error. No valid " + c_type.getDisplayName() + " station modes are configured.  You will not be able to run this simulation.  Please contact your system administrator.", JOptionPane.ERROR_MESSAGE) {
                            private static final long serialVersionUID = 1L;

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

                        JDialog dialog = pane.createDialog(c_type.getDisplayName() + " Station Mode");
                        dialog.setModal(true);
                        dialog.setVisible(true);
                        setStationMode(null);

                    }
                };

            case 1:
                //inform the user that the property is being changed.
                throw new PropertyVetoRunnableException(newMode.getDisplayName() + " is not an allowed " + c_type.getDisplayName() + " station mode.", event) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void run() {
                        JOptionPane pane = new JOptionPane("The simulation you are attempting to open uses an invalid " + c_type.getDisplayName() + " station mode. " + newMode.getDisplayName() + " is not allowed. Setting mode to " + allowed[0].getDisplayName() + ".", JOptionPane.WARNING_MESSAGE) {
                            private static final long serialVersionUID = 1L;

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

                        JDialog dialog = pane.createDialog(c_type.getDisplayName() + " Station Mode");
                        dialog.setModal(true);
                        dialog.setVisible(true);

                        //set to the first and only allowed mode
                        setStationMode(allowed[0]);
                    }
                };

            default:
                //show the mode chooser
                throw new PropertyVetoRunnableException(newMode.getDisplayName() + " is not an allowed " + c_type.getDisplayName() + " station mode.", event) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void run() {
                        StationModeChooser smc = new StationModeChooser(allowedModes(), null);
                        smc.setLabelText("The simulation you are attempting to open uses an invalid " + c_type.getDisplayName() + " station mode. " + newMode.getDisplayName() + " is not allowed. Please select a valid station mode.");

                        JOptionPane pane = new JOptionPane(smc, JOptionPane.WARNING_MESSAGE);

                        final JDialog dialog = pane.createDialog(c_type.getDisplayName() + " Station Mode");
                        dialog.setModal(true);
                        //fork the pack to happen after the setVisible
                        EventQueue.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                dialog.pack();
                            }
                        });
                        dialog.setVisible(true);


                        setStationMode(smc.getSelectedStationMode());

                    }
                };
        }




    }

	/**
	 *
	 * @param event
	 * @throws PropertyVetoException
	 */
	@Override
    public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException {

        StationMode oldMode = null;
        StationMode newMode = null;

        if (event.getOldValue() instanceof StationMode) {
            oldMode = (StationMode) event.getOldValue();
        }

        if (event.getNewValue() instanceof StationMode) {
            newMode = (StationMode) event.getNewValue();
        }

        validate(allowedModes(), oldMode, newMode, event);

    }

    private StationMode[] allowedModes() {
        switch (c_type) {
            case Cligen:
                return ConfigData.getDefault().getAllowedCligenStationModes();
            case Windgen:
                return ConfigData.getDefault().getAllowedWindgenStationModes();
            default:
                //stop here and just return an empty array
                return new StationMode[0];
        }
    }
}
