/*
 * LocationPanel.java
 *
 * Created on Jul 30, 2009, 4:22:12 PM
 */
package usda.weru.weps.location;

import java.awt.EventQueue;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.help.CSH;
import tec.uom.se.quantity.Quantities;
import systems.uom.common.USCustomary;
import tec.uom.se.unit.MetricPrefix;
import si.uom.SI;
import javax.measure.Unit;
import javax.measure.Quantity;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Length;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 
import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.beansbinding.Bindings;

import usda.weru.gis.latlong.LatLong;
import usda.weru.gis.GISUtil;
import usda.weru.gis.gui.MapController;
import usda.weru.gis.gui.MapViewer;
import usda.weru.util.ConfigData;
import usda.weru.util.MeasurableField;
import usda.weru.util.MeasurableField.ValueListener;
import usda.weru.util.Util;
import usda.weru.weps.RunFileBean;
import usda.weru.weps.RunFileData;
import usda.weru.weps.location.chooser.SiteChooser;
import usda.weru.weps.location.chooser.StationChooser;
import usda.weru.util.wepsFileChooser2.WepsFileTypes2;
import usda.weru.weps.Weps;

/**
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class LocationPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = LogManager.getLogger(LocationPanel.class);
    private final RunFileBean c_rfb;
    private LatLong c_latlong;
    private boolean siteChanged = true;
    private int restoreCounter=0;
    private static Weps wInstance;
    private MapViewer c_mapViewer;

    public LocationPanel(RunFileBean rfb) {
        this (rfb, null);
    }

    public LocationPanel(RunFileBean rfb, Weps w) {
        c_rfb = rfb;
        //let's get this show going.
        initComponents();
        // While the viewer is initializing, disable
        mapButton.setEnabled(false);
        
        addHelp();
        wInstance = w;
        //link the stationchoosers to their bean and station type
        cligenStationChooser.setRunFileBean(c_rfb);
        cligenStationChooser.setStationType(RunFileBean.StationType.Cligen);

        windgenStationChooser.setRunFileBean(c_rfb);
        windgenStationChooser.setStationType(RunFileBean.StationType.Windgen);

        //init the settings that come from the CD
        updateUnits();
        updateSiteChooserRoot();
        
        initListeners();
        initBindings();
    }
    
    public void setWepsInstance(Weps w) {
        wInstance = w;
    }
    
    private void initListeners() {
        //user editor latlong
        ValueListener<Angle> latlongValueListener = new ValueListener<Angle>() {

            @Override
            public void valueChanged(Quantity<Angle> oldValue, Quantity<Angle> newValue) {
                siteChanged = false;
                mapButton.setText("Field Location Selected");
                wInstance.rfd.setData(RunFileData.SelectFieldLocTxt, "Field Location Selected");
                double lat = latitudeField.getValue().to(USCustomary.DEGREE_ANGLE).getValue().doubleValue();
                double lon = longitudeField.getValue().to(USCustomary.DEGREE_ANGLE).getValue().doubleValue();
                c_rfb.setLatLong(LatLong.valueOf(lat, lon, USCustomary.DEGREE_ANGLE));
            }
        };
        longitudeField.addValueListener(latlongValueListener);
        latitudeField.addValueListener(latlongValueListener);
        c_rfb.addPropertyChangeListener(RunFileBean.PROP_LATLONG, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                updateLatLong();
            }
        });
        
          c_rfb.addPropertyChangeListener(RunFileBean.PROP_CLIGEN_STATION, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                Quantity<Length> value = ((CligenStation)evt.getNewValue()).getElevation();
                elevationField.setValue(value);
            }
        });


        //configdata units
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.Units, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                updateUnits();
            }
        });

        ConfigData.getDefault().addPropertyChangeListener(ConfigData.SiteChooserShowCountry, (PropertyChangeEvent evt) -> {
            updateSiteChooserRoot();
        });

        //enabled cligen modes
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.CligenEnabledModes, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                cligenStationChooser.setStationModes(StationMode.parseStationModes((String)evt.getNewValue()));
            }
        });
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.CligenDefaultMode, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                cligenStationChooser.setDefaultStationMode((String)evt.getNewValue());
            }
        });


        //enabled windgen modes
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.WindgenEnabledModes, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                windgenStationChooser.setStationModes(StationMode.parseStationModes((String)evt.getNewValue()));
            }
        });
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.WindgenDefaultMode, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                windgenStationChooser.setDefaultStationMode((String)evt.getNewValue());
            }
        });
        
        //cligen radius
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.ClimateRadius, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                //System.out.println("The cligen radius has been changed.");
                cligenStationChooser.setDistance(ConfigData.getDefault().getCligenSearchRadius());
                // MEH
                // getLatLong is null at startup time, set at runtime
                // If this is a runtime change, i.e. ConfigPanel) 
                // then update it so that the new distance takes effect
                if (cligenStationChooser.getLatLong() != null) {
                    StationMode oldMode = cligenStationChooser.getStationMode();
                    cligenStationChooser.setStationMode(null);
                    cligenStationChooser.setStationMode(oldMode);
                }
            }
        });
        
        //windgen radius
        ConfigData.getDefault().addPropertyChangeListener(ConfigData.WindRadius, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                //System.out.println("The windgen radius has been changed.");
                //windgenStationChooser.setAllowedStationModes(ConfigData.getDefault().getAllowedWindgenStationModes());
                // MEH
                // getLatLong is null at startup time, set at runtime
                // If this is a runtime change, i.e. ConfigPanel) 
                // then update it so that the new distance takes effect
                if (windgenStationChooser.getLatLong() != null) {
                    StationMode oldMode = windgenStationChooser.getStationMode();
                    windgenStationChooser.setStationMode(null);
                    windgenStationChooser.setStationMode(oldMode);
                }
            }
        });
    }

    private void initBindings() {
        //add the bean bindings
        BindingGroup bindings = new BindingGroup();
        //elevation
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, c_rfb,
                BeanProperty.create(RunFileBean.PROP_ELEVATION), elevationField,
                BeanProperty.create(MeasurableField.PROP_VALUE)));
        //cligen mode
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, c_rfb,
                BeanProperty.create(RunFileBean.PROP_CLIGEN_STATION_MODE), cligenStationChooser,
                BeanProperty.create(StationChooser.PROP_STATION_MODE)));
        //cligen station
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, c_rfb,
                BeanProperty.create(RunFileBean.PROP_CLIGEN_STATION), cligenStationChooser,
                BeanProperty.create(StationChooser.PROP_SELECTED_STATION)));
        //latlong
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ, c_rfb,
                BeanProperty.create(RunFileBean.PROP_LATLONG), cligenStationChooser,
                BeanProperty.create(StationChooser.PROP_LATLONG)));
        //windgen mode
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, c_rfb,
                BeanProperty.create(RunFileBean.PROP_WINDGEN_STATION_MODE), windgenStationChooser,
                BeanProperty.create(StationChooser.PROP_STATION_MODE)));
        //windgen station
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, c_rfb,
                BeanProperty.create(RunFileBean.PROP_WINDGEN_STATION), windgenStationChooser,
                BeanProperty.create(StationChooser.PROP_SELECTED_STATION)));
        //latlong
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ, c_rfb,
                BeanProperty.create(RunFileBean.PROP_LATLONG), windgenStationChooser,
                BeanProperty.create(StationChooser.PROP_LATLONG)));
        //site
        bindings.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, c_rfb,
                BeanProperty.create(RunFileBean.PROP_SITE), siteChooser,
                BeanProperty.create(SiteChooser.PROP_SELECTED_SITE)));

        bindings.bind();

    }

    public RunFileBean getRunFileBean() {
        return c_rfb;
    }

    private void updateLatLong() {
        restoreCounter++;
        //if this is from a restoration change map button to say "Field location presumed selected"
        if(wInstance.isRestored && restoreCounter>1){
                mapButton.setText("Field Location Presumed Selected");
                siteChanged = false;
                wInstance.rfd.setData(RunFileData.SelectFieldLocTxt, "Field Location Presumed Selected");
        }
        if(siteChanged){
                mapButton.setText("Please Select Field Location");
                wInstance.rfd.setData(RunFileData.SelectFieldLocTxt, "Please Select Field Location");
                wInstance.rfd.setData(RunFileBean.PROP_CLIGEN_STATION, "site change");
                
        }
        c_latlong = c_rfb.getLatLong();
        if (c_latlong == null) {
            LOGGER.warn("LatLong is null.  Unable to update the lat long fields.");
            latitudeField.setValue(Quantities.getQuantity(0, USCustomary.DEGREE_ANGLE));
            longitudeField.setValue(Quantities.getQuantity(0, USCustomary.DEGREE_ANGLE));
            JOptionPane.showMessageDialog(this, "Unable to determine latitude and longitude.",
                    "Invalid Data", JOptionPane.WARNING_MESSAGE);
            latitudeField.requestFocusInWindow();
            longitudeField.requestFocusInWindow();
            return;
        }
        double lat = c_latlong.latitudeValue(USCustomary.DEGREE_ANGLE);
        latitudeField.setValue(Quantities.getQuantity(lat, USCustomary.DEGREE_ANGLE));

        double lon = c_latlong.longitudeValue(USCustomary.DEGREE_ANGLE);
        longitudeField.setValue(Quantities.getQuantity(lon, USCustomary.DEGREE_ANGLE));
        wInstance.isRestored=false;
        siteChanged = true;
        
        if (c_mapViewer != null) {
            c_mapViewer.setSelectedLatLongExternal(c_latlong);
        }
    }

    private void updateSiteChooserRoot() {
        Site<?> currentValue = siteChooser.getSelectedSite();
        if (ConfigData.getDefault().isSiteChooserShowCountries()) {
            siteChooser.setRootSite(null);
        } else {
            siteChooser.setRootSite(Site.UNITED_STATES);
        }
        siteChooser.setSelectedSite(currentValue); 
    }

    private void updateUnits() {
        Unit<Length> distanceUnit = MetricPrefix.KILO(SI.METRE);
        Unit<Length> elevationUnit = SI.METRE;
        if (Util.USUnits.equals(ConfigData.getDefault().getData(ConfigData.Units))) {
            distanceUnit = USCustomary.MILE;
            elevationUnit = USCustomary.FOOT;
        }
        cligenStationChooser.setDistanceUnits(distanceUnit);
        windgenStationChooser.setDistanceUnits(distanceUnit);
        elevationField.setUnits(elevationUnit);

        //lat long always uses degree angle
        latitudeField.setUnits(USCustomary.DEGREE_ANGLE);
        longitudeField.setUnits(USCustomary.DEGREE_ANGLE);
    }

    /**
     * This panel holds all the location information for the wind and climate generation station like
     * the latitudes and longitudes passing through it, the county and state in which they fall, etc.
     * @param sTitle The string that carries the title for the panel.
     */
    private void addHelp() {
        CSH.setHelpIDString(siteLabel, "scSelection_html");
        CSH.setHelpIDString(siteChooser, "scSelection_html");
        CSH.setHelpIDString(this, "locationPanel_html");
        CSH.setHelpIDString(logitudeLabel, "llSelection_html");
        CSH.setHelpIDString(longitudeField, "llSelection_html");
        CSH.setHelpIDString(latitudeLabel, "llSelection_html");
        CSH.setHelpIDString(latitudeField, "llSelection_html");
        CSH.setHelpIDString(elevationLabel, "locationPanel_html");
        CSH.setHelpIDString(elevationField, "locationPanel_html");
        CSH.setHelpIDString(cligenLabelPanel, "ssMethods_html");
        CSH.setHelpIDString(cligenStationChooser, "ssMethods_html");
        CSH.setHelpIDString(windgenLabelPanel, "ssMethods_html");
        CSH.setHelpIDString(windgenStationChooser, "ssMethods_html");
        CSH.setHelpIDString(mapButton, "mvSelection_html");
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        cligenLabelPanel = new javax.swing.JPanel();
        cligenLabel = new javax.swing.JLabel();
        cligenSubLabel = new javax.swing.JLabel();
        cligenStationChooser = new usda.weru.weps.location.chooser.StationChooser();
        windgenLabelPanel = new javax.swing.JPanel();
        windgenLabel = new javax.swing.JLabel();
        windgenSubLabel = new javax.swing.JLabel();
        windgenStationChooser = new usda.weru.weps.location.chooser.StationChooser();
        latitudeLabel = new javax.swing.JLabel();
        logitudeLabel = new javax.swing.JLabel();
        elevationLabel = new javax.swing.JLabel();
        elevationUnits = new javax.swing.JLabel();
        mapButtonPanel = new javax.swing.JPanel();
        logitudeUnits = new javax.swing.JLabel();
        latitudeUnits = new javax.swing.JLabel();
        elevationField = new usda.weru.util.MeasurableField<>();
        latitudeField = new usda.weru.util.MeasurableField<>();
        longitudeField = new usda.weru.util.MeasurableField<>();
        siteChooser = new usda.weru.weps.location.chooser.SiteChooser();
        siteLabel = siteChooser.getLabelPanel();
        mapButton = new javax.swing.JButton();

        cligenLabel.setText("Cligen:");

        cligenSubLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        cligenSubLabel.setText(" ");

        javax.swing.GroupLayout cligenLabelPanelLayout = new javax.swing.GroupLayout(cligenLabelPanel);
        cligenLabelPanel.setLayout(cligenLabelPanelLayout);
        cligenLabelPanelLayout.setHorizontalGroup(
            cligenLabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(cligenLabelPanelLayout.createSequentialGroup()
                .addComponent(cligenLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(cligenSubLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        cligenLabelPanelLayout.setVerticalGroup(
            cligenLabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(cligenLabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(cligenLabel)
                .addComponent(cligenSubLabel))
        );

        cligenStationChooser.setFileType(WepsFileTypes2.Climate);
        cligenStationChooser.setLabel(cligenLabel);
        cligenStationChooser.setName("cligenChooser"); // NOI18N
        cligenStationChooser.setSubLabel(cligenSubLabel);

        windgenLabel.setText("Windgen:");

        windgenSubLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        windgenSubLabel.setText(" ");

        javax.swing.GroupLayout windgenLabelPanelLayout = new javax.swing.GroupLayout(windgenLabelPanel);
        windgenLabelPanel.setLayout(windgenLabelPanelLayout);
        windgenLabelPanelLayout.setHorizontalGroup(
            windgenLabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(windgenLabelPanelLayout.createSequentialGroup()
                .addComponent(windgenLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(windgenSubLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        windgenLabelPanelLayout.setVerticalGroup(
            windgenLabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(windgenLabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(windgenLabel)
                .addComponent(windgenSubLabel))
        );

        windgenStationChooser.setFileType(WepsFileTypes2.Wind);
        windgenStationChooser.setLabel(windgenLabel);
        windgenStationChooser.setName("windgenChooser"); // NOI18N
        windgenStationChooser.setSubLabel(windgenSubLabel);

        latitudeLabel.setText("Latitude:");

        logitudeLabel.setText("Longitude:");

        elevationLabel.setText("Elevation:");

        elevationField.setDefaultPattern("#0");
        elevationField.setDisplayPattern("#0");
        elevationField.setEditPattern("#0.0");
        elevationField.setUnitsLabel(elevationUnits);

        latitudeField.setDisplayPattern("0.00000 N;0.00000 S");
        latitudeField.setEditPattern("0.00000;-0.00000");
        latitudeField.setUnitsLabel(latitudeUnits);

        longitudeField.setDisplayPattern("0.00000 E;0.00000 W");
        longitudeField.setEditPattern("0.00000;-0.00000");
        longitudeField.setUnitsLabel(logitudeUnits);

        siteLabel.setLayout(new java.awt.GridLayout(0, 1));

        mapButton.setText(RunFileData.SelectFieldLocTxt);
        mapButton.setActionCommand("");
        mapButton.setName("RFD-SelectFieldLocTxt"); // NOI18N
        mapButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mapButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mapButtonPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(windgenStationChooser, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 247, Short.MAX_VALUE)
                    .addComponent(cligenStationChooser, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(windgenLabelPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(cligenLabelPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(siteLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(logitudeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(elevationLabel)
                            .addComponent(latitudeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(mapButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(siteChooser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(elevationField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(latitudeField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(longitudeField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(elevationUnits, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(logitudeUnits, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(latitudeUnits, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(siteLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(siteChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(mapButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(latitudeLabel)
                    .addComponent(latitudeUnits)
                    .addComponent(latitudeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(logitudeLabel)
                    .addComponent(logitudeUnits)
                    .addComponent(longitudeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(elevationLabel)
                    .addComponent(elevationUnits)
                    .addComponent(elevationField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(cligenLabelPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cligenStationChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(windgenLabelPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, 0)
                .addComponent(windgenStationChooser, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(mapButtonPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {siteChooser, siteLabel});

        mapButton.getAccessibleContext().setAccessibleName("RFD-SelectFieldLocTxt");
    }// </editor-fold>//GEN-END:initComponents

    private void mapButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mapButtonActionPerformed
        //show the viewer
        c_mapViewer.setCurrentLocationMarker(c_rfb.getLatLong());
        MapController control = c_mapViewer.getMapController();
        control.setCenter(GISUtil.toCoordinate(c_rfb.getLatLong()));

        int state = c_mapViewer.getExtendedState();
        //remove any iconified bits
        state &= ~JFrame.ICONIFIED;
        c_mapViewer.setExtendedState(state);
        //bring it to the front
        c_mapViewer.toFront();
        c_mapViewer.setVisible(true);
    }//GEN-LAST:event_mapButtonActionPerformed

    protected void initMapViewerInThread () {
        new Thread(new Runnable() {
            @Override
            public void run() {
                initMapViewer();
            }
        }).start();
    }
    
    protected void initMapViewer () {
        MapViewer oldViewer = null;
        if (c_mapViewer != null) {
            oldViewer = c_mapViewer;
            c_mapViewer.setVisible(false);
            c_mapViewer = null;
        }
        c_mapViewer = new MapViewer();
        c_mapViewer.initContent();
        c_mapViewer.setSelectedLatLongExternal(c_latlong);

        final PropertyChangeListener latLongListener = new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if(c_mapViewer != null) {
                    System.out.println("Updating location marker in Map Viewer.");
                    c_mapViewer.setCurrentLocationMarker(c_rfb.getLatLong());
                } else {
                    System.out.println("Not updating location marker in Map Viewer, it has been closed.");
                }
            }
        };

        c_rfb.addPropertyChangeListener(RunFileBean.PROP_LATLONG, latLongListener);

        c_mapViewer.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosed(WindowEvent e) {
                c_rfb.removePropertyChangeListener(RunFileBean.PROP_LATLONG, latLongListener);
                c_mapViewer = null;
            }
        });

        c_mapViewer.addPropertyChangeListener(MapViewer.PROP_SELECTEDLATLONG, new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                mapButton.setText("Field Location Selected");
                wInstance.rfd.setData(RunFileData.SelectFieldLocTxt, "Field Location Selected");
                siteChanged = false;
                c_rfb.setLatLong(c_mapViewer.getSelectedLatLong());
            }
        });

        c_mapViewer.addPropertyChangeListener(MapViewer.PROP_RESETLATLONG, new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                mapButton.setText("Please Select Field Location");
                wInstance.rfd.setData(RunFileData.SelectFieldLocTxt, "Please Select Field Location");
                siteChanged = false;
                c_rfb.setLatLong(c_mapViewer.getSelectedLatLong());
            }
        });
        
        if (oldViewer != null) {
            c_mapViewer.setZoomBarExternal(oldViewer.getViewerCurrentZoomVal());
        }
        mapButton.setEnabled(true);
    }
    
    // called when ConfigData for MapViewer changes.
    // reload a new MapViewer with the new data.
    public void reloadMapViewer () {
        mapButton.setEnabled(false);
        initMapViewerInThread ();
    }
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel cligenLabel;
    private javax.swing.JPanel cligenLabelPanel;
    private usda.weru.weps.location.chooser.StationChooser cligenStationChooser;
    private javax.swing.JLabel cligenSubLabel;
    private usda.weru.util.MeasurableField<Length> elevationField;
    private javax.swing.JLabel elevationLabel;
    private javax.swing.JLabel elevationUnits;
    private usda.weru.util.MeasurableField<Angle> latitudeField;
    private javax.swing.JLabel latitudeLabel;
    private javax.swing.JLabel latitudeUnits;
    private javax.swing.JLabel logitudeLabel;
    private javax.swing.JLabel logitudeUnits;
    private usda.weru.util.MeasurableField<Angle> longitudeField;
    public javax.swing.JButton mapButton;
    private javax.swing.JPanel mapButtonPanel;
    private usda.weru.weps.location.chooser.SiteChooser siteChooser;
    private javax.swing.JPanel siteLabel;
    private javax.swing.JLabel windgenLabel;
    private javax.swing.JPanel windgenLabelPanel;
    private usda.weru.weps.location.chooser.StationChooser windgenStationChooser;
    private javax.swing.JLabel windgenSubLabel;
    // End of variables declaration//GEN-END:variables

    public void refreshRadiusElements() {
    }
    
    public LatLong getLatLong() {
        return c_latlong;
    }
    
    public double getLatitudeValue() {
        return c_latlong.latitudeValue(USCustomary.DEGREE_ANGLE);
    }
    
    public double getLongitudeValue() {
        return c_latlong.longitudeValue(USCustomary.DEGREE_ANGLE);
    }
    
    public static void main(String[] args) {
        final JFrame frame = new JFrame("Location Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new LocationPanel(new RunFileData().getBean()));

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                frame.setVisible(true);
                frame.pack();
            }
        });
    }
    
    public void updateViewer () {
        c_mapViewer.resetCachePaths();
    }
    
    public Site<?> getSelectedSite() {
        if (siteChooser.getSelectedSite() == null) {
            return null;
        } else {
            Site<?> nwst = siteChooser.getSelectedSite();
            return siteChooser.getSelectedSite();
        }
    }
    
    public SiteChooser getSiteChooser() {
        return siteChooser;
    }
    
    public void resetChooserToDefaults () {
        cligenStationChooser.setDefaultStationMode(ConfigData.getDefault().
                getData(ConfigData.CligenDefaultMode));
        windgenStationChooser.setDefaultStationMode(ConfigData.getDefault().
                getData(ConfigData.WindgenDefaultMode));
        
    }
}
