/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MapViewer.java
 *
 * Created on Jun 30, 2009, 4:14:25 PM
 */
package usda.weru.gis.gui;

import com.vividsolutions.jts.geom.Coordinate;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.measure.unit.NonSI;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.geotools.data.DataStore;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.map.DefaultMapContext;
import org.geotools.map.DefaultMapLayer;
import org.geotools.map.MapContext;
import org.geotools.map.MapLayer;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.Style;
import org.jscience.geography.coordinates.LatLong;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.Name;
import org.opengis.geometry.primitive.Point;
import usda.weru.gis.GISData;
import usda.weru.gis.GISLookup;
import usda.weru.gis.GISUtil;
import usda.weru.gis.MapData;
import usda.weru.gis.data.CropManagementZone;
import usda.weru.gis.data.Territory;
import usda.weru.weps.location.CligenDataModel;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.WindgenDataModel;

/**
 *
 * @author Joseph A. Levin <joelevin@weru.ksu.edu>
 */
public class MapViewer extends javax.swing.JFrame {

    private MapController c_controller;
    private LatLong c_selectedLatLong;
    public static final String PROP_SELECTEDLATLONG = "selectedLatLong";
    private MapLayer c_currentLocationLayer;

    private static Rectangle c_restoreBounds;
    private int c_restoreState;

        /** Creates new form MapViewer */
    public MapViewer() {
        initComponents();

        demoWingen.setVisible(false);
        demoWingenLabel.setVisible(false);
        demoCligen.setVisible(false);
        demoCligenLabel.setVisible(false);


        //loading, restore size and location if possible
        Rectangle bounds;
        int state;
        synchronized(MapViewer.class){
            bounds = c_restoreBounds;
            state = c_restoreState;
        }
        if(bounds != null){
            setBounds(bounds);
            setExtendedState(state);
        }

        //when a window is closing, save its state
         addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                synchronized(MapViewer.class){
                    c_restoreBounds = getBounds();
                    c_restoreState = getExtendedState();
                }
            }



        });

        c_controller = mapPane.getMapLayer();

       



        //selection handler
        MouseAdapter selection = new InternalSelectionHandler();
        c_controller.addMouseListener(selection);
        c_controller.addMouseMotionListener(selection);

        setMapContext(createDefaultContext());

    }
    

    LayerTableModel c_model;
    public void setMapContext(MapContext map) {
        try {

            mapPane.getMapLayer().setMapContext(map);
            c_model =new LayerTableModel(map);
            layerTable.setModel(c_model);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public MapContext getMapContext(){
        return mapPane.getMapLayer().getMapContext();
    }

    public void setCurrentLocationMarker(final LatLong location){        
        MapLayer old = c_currentLocationLayer;
        c_currentLocationLayer = createLatLongMarkerLayer(location);
        if(old != null){
            getMapContext().removeLayer(old);
        }
        
        getMapContext().addLayer(c_currentLocationLayer);
    }

    private MapLayer createLatLongMarkerLayer(LatLong location){

        Coordinate center = GISUtil.toCoordinate(location);

        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("markerType");
        typeBuilder.setNamespaceURI("usda.weru.gis");
//        typeBuilder.setSRS("WGS84");

        typeBuilder.add("location", Point.class);
        typeBuilder.setDefaultGeometry("location");
        
        typeBuilder.add("name", String.class);
        

        SimpleFeatureType markerType = typeBuilder.buildFeatureType();

        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(markerType);
               

        builder.add(new com.vividsolutions.jts.geom.GeometryFactory().createPoint(center));
//                builder.add(point);
        builder.add("Current LatLong");        

        FeatureCollection collection = new DefaultFeatureCollection("latlongMarker", markerType);
        SimpleFeature marker = builder.buildFeature(null);
        collection.add(marker);



        Style style = GISGUIUtil.createCrossPointStyle(Color.RED, Color.PINK);
        

        MapLayer layer = new DefaultMapLayer(collection, style, "Current Location");

        return layer;
    }

    private MapLayer createWindgenStationLayer(){

        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("windgenStation");
        typeBuilder.setNamespaceURI("usda.weru.gis");
//        typeBuilder.setSRS("WGS84");

        typeBuilder.add("location", Point.class);
        typeBuilder.setDefaultGeometry("location");

        typeBuilder.add("name", String.class);


        SimpleFeatureType markerType = typeBuilder.buildFeatureType();

        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(markerType);

        FeatureCollection collection = new DefaultFeatureCollection("windgenStations", markerType);


        WindgenDataModel data = WindgenDataModel.getInstance();
        for(Station station : data.stations()){
            builder.reset();
            builder.add(new com.vividsolutions.jts.geom.GeometryFactory().createPoint(GISUtil.toCoordinate(station.getLatLong())));
            builder.add(station.getDisplayName());
            SimpleFeature marker = builder.buildFeature(null);
            collection.add(marker);
        }



        



        Style style = GISGUIUtil.createCirclePointStyle(5, Color.RED, Color.GRAY);


        MapLayer layer = new DefaultMapLayer(collection, style, "Windgen Stations");
        layer.setVisible(false);

        return layer;
    }

    private MapLayer createCligenStationLayer(){

        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("cligenStation");
        typeBuilder.setNamespaceURI("usda.weru.gis");
//        typeBuilder.setSRS("WGS84");

        typeBuilder.add("location", Point.class);
        typeBuilder.setDefaultGeometry("location");

        typeBuilder.add("name", String.class);


        SimpleFeatureType markerType = typeBuilder.buildFeatureType();

        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(markerType);

        FeatureCollection collection = new DefaultFeatureCollection("cligenStations", markerType);


        CligenDataModel data = CligenDataModel.getInstance();
        for(Station station : data.stations()){
            builder.reset();
            builder.add(new com.vividsolutions.jts.geom.GeometryFactory().createPoint(GISUtil.toCoordinate(station.getLatLong())));
            builder.add(station.getDisplayName());
            SimpleFeature marker = builder.buildFeature(null);
            collection.add(marker);
        }

        Style style = GISGUIUtil.createCirclePointStyle(5, Color.BLUE, Color.GRAY);


        MapLayer layer = new DefaultMapLayer(collection, style, "Cligen Stations");
        layer.setVisible(false);

        return layer;
    }



    private MapContext createDefaultContext() {
        final MapContext context = new DefaultMapContext(DefaultGeographicCRS.WGS84);

        Thread task = new Thread("GIS Map Loader") {

            @Override
            public void run() {
                
                
                GISData data = GISData.getInstance();

                try {
                   
                    for (Name name : data.getNames()) {
                        DataStore store = data.dataStore(name);
                        //hack for visibility
                        boolean visible = MapData.isLayerVisibleDefault(name);
                        context.addLayers(getLayers(store, visible));
                    }

                    context.addLayer(createWindgenStationLayer());
                    context.addLayer(createCligenStationLayer());

                    while(c_currentLocationLayer == null && context.indexOf(c_currentLocationLayer) < 0){
                        Thread.yield();
                    }
                    context.moveLayer(context.indexOf(c_currentLocationLayer), context.getLayerCount() -1);
                    
                    
                    

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
        };

        task.start();
        return context;
    }

    

    private static MapLayer[] getLayers(DataStore store, boolean visible) {
        MapData test = new MapData();
        List<MapLayer> layers = new ArrayList<MapLayer>();


        try {
            for (String typeName : store.getTypeNames()) {
                MapLayer l = test.createLayer(store.getFeatureSource(typeName));
                l.setVisible(visible);
                layers.add(l);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        MapLayer[] temp = layers.toArray(new MapLayer[layers.size()]);        
        return temp;
    }

    public MapController getMapController() {
        return mapPane.getMapLayer();
    }

    public LatLong getSelectedLatLong() {
        return c_selectedLatLong;
    }

    public void setSelectedLatLong(LatLong latlong) {
        LatLong old = c_selectedLatLong;
        c_selectedLatLong = latlong;
        firePropertyChange(PROP_SELECTEDLATLONG, old, c_selectedLatLong);

    }

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

        splitPanel = new javax.swing.JSplitPane();
        sidePanel = new javax.swing.JPanel();
        tableScrollPanel = new javax.swing.JScrollPane();
        layerTable = new javax.swing.JTable();
        demoCountryLabel = new javax.swing.JLabel();
        demoStateLabel = new javax.swing.JLabel();
        demoCountyLabel = new javax.swing.JLabel();
        demoCMZLabel = new javax.swing.JLabel();
        demoWingenLabel = new javax.swing.JLabel();
        demoCligenLabel = new javax.swing.JLabel();
        demoCMZ = new javax.swing.JLabel();
        demoCountry = new javax.swing.JLabel();
        demoState = new javax.swing.JLabel();
        demoCounty = new javax.swing.JLabel();
        demoWingen = new javax.swing.JLabel();
        demoCligen = new javax.swing.JLabel();
        demoPositionLabel = new javax.swing.JLabel();
        demoPosition = new javax.swing.JLabel();
        mainPanel = new javax.swing.JPanel();
        statusBar = new javax.swing.JPanel();
        statusLabel = new javax.swing.JLabel();
        latLonField = new javax.swing.JFormattedTextField();
        mapPane = new usda.weru.gis.gui.MapPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("usda/weru/gis/gui/Bundle"); // NOI18N
        setTitle(bundle.getString("MapViewer.title")); // NOI18N

        splitPanel.setDividerLocation(200);

        layerTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
        layerTable.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                layerTableMouseClicked(evt);
            }
        });
        tableScrollPanel.setViewportView(layerTable);

        demoCountryLabel.setFont(demoCountryLabel.getFont().deriveFont(demoCountryLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoCountryLabel.setText(bundle.getString("MapViewer.demoCountryLabel.text")); // NOI18N

        demoStateLabel.setFont(demoStateLabel.getFont().deriveFont(demoStateLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoStateLabel.setText(bundle.getString("MapViewer.demoStateLabel.text")); // NOI18N

        demoCountyLabel.setFont(demoCountyLabel.getFont().deriveFont(demoCountyLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoCountyLabel.setText(bundle.getString("MapViewer.demoCountyLabel.text")); // NOI18N

        demoCMZLabel.setFont(demoCMZLabel.getFont().deriveFont(demoCMZLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoCMZLabel.setText(bundle.getString("MapViewer.demoCMZLabel.text")); // NOI18N

        demoWingenLabel.setFont(demoWingenLabel.getFont().deriveFont(demoWingenLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoWingenLabel.setText(bundle.getString("MapViewer.demoWingenLabel.text")); // NOI18N

        demoCligenLabel.setFont(demoCligenLabel.getFont().deriveFont(demoCligenLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoCligenLabel.setText(bundle.getString("MapViewer.demoCligenLabel.text")); // NOI18N

        demoCMZ.setFont(demoCMZ.getFont().deriveFont(demoCMZ.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoCMZ.setText(bundle.getString("MapViewer.demoCMZ.text")); // NOI18N

        demoCountry.setFont(demoCountry.getFont().deriveFont(demoCountry.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoCountry.setText(bundle.getString("MapViewer.demoCountry.text")); // NOI18N

        demoState.setFont(demoState.getFont().deriveFont(demoState.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoState.setText(bundle.getString("MapViewer.demoState.text")); // NOI18N

        demoCounty.setFont(demoCounty.getFont().deriveFont(demoCounty.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoCounty.setText(bundle.getString("MapViewer.demoCounty.text")); // NOI18N

        demoWingen.setFont(demoWingen.getFont().deriveFont(demoWingen.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoWingen.setText(bundle.getString("MapViewer.demoWingen.text")); // NOI18N

        demoCligen.setFont(demoCligen.getFont().deriveFont(demoCligen.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoCligen.setText(bundle.getString("MapViewer.demoCligen.text")); // NOI18N

        demoPositionLabel.setFont(demoPositionLabel.getFont().deriveFont(demoPositionLabel.getFont().getStyle() | java.awt.Font.BOLD));
        demoPositionLabel.setText(bundle.getString("MapViewer.demoPositionLabel.text")); // NOI18N

        demoPosition.setFont(demoPosition.getFont().deriveFont(demoPosition.getFont().getStyle() & ~java.awt.Font.BOLD));
        demoPosition.setText(bundle.getString("MapViewer.demoPosition.text")); // NOI18N

        javax.swing.GroupLayout sidePanelLayout = new javax.swing.GroupLayout(sidePanel);
        sidePanel.setLayout(sidePanelLayout);
        sidePanelLayout.setHorizontalGroup(
            sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(sidePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(sidePanelLayout.createSequentialGroup()
                        .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(demoCountryLabel)
                            .addComponent(demoStateLabel)
                            .addComponent(demoCMZLabel)
                            .addComponent(demoCountyLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(demoCounty, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE)
                            .addComponent(demoCMZ, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE)
                            .addComponent(demoState, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE)
                            .addComponent(demoCountry, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE)))
                    .addGroup(sidePanelLayout.createSequentialGroup()
                        .addComponent(demoPositionLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(demoPosition, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, sidePanelLayout.createSequentialGroup()
                        .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(demoWingenLabel)
                            .addComponent(demoCligenLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(demoCligen, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE)
                            .addComponent(demoWingen, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE))))
                .addContainerGap())
            .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(sidePanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(tableScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE)
                    .addContainerGap()))
        );
        sidePanelLayout.setVerticalGroup(
            sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(sidePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoPositionLabel)
                    .addComponent(demoPosition))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoCountryLabel)
                    .addComponent(demoCountry))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoStateLabel)
                    .addComponent(demoState))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoCountyLabel)
                    .addComponent(demoCounty))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoCMZLabel)
                    .addComponent(demoCMZ))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoWingenLabel)
                    .addComponent(demoWingen))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(demoCligenLabel)
                    .addComponent(demoCligen))
                .addContainerGap(353, Short.MAX_VALUE))
            .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, sidePanelLayout.createSequentialGroup()
                    .addContainerGap(303, Short.MAX_VALUE)
                    .addComponent(tableScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 184, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap()))
        );

        splitPanel.setLeftComponent(sidePanel);

        statusBar.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        statusLabel.setText(bundle.getString("MapViewer.statusLabel.text")); // NOI18N

        latLonField.setEditable(false);
        latLonField.setFormatterFactory(new LatLonFormatterFactory());
        latLonField.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        latLonField.setText(bundle.getString("MapViewer.latLonField.text")); // NOI18N

        javax.swing.GroupLayout statusBarLayout = new javax.swing.GroupLayout(statusBar);
        statusBar.setLayout(statusBarLayout);
        statusBarLayout.setHorizontalGroup(
            statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusBarLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 258, Short.MAX_VALUE)
                .addComponent(latLonField, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, 0))
        );
        statusBarLayout.setVerticalGroup(
            statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, statusBarLayout.createSequentialGroup()
                .addGap(0, 0, 0)
                .addGroup(statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
                    .addComponent(latLonField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        mapPane.setBackground(new java.awt.Color(255, 255, 255));
        mapPane.setOpaque(true);

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(mapPane, javax.swing.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE)
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                .addComponent(mapPane, javax.swing.GroupLayout.DEFAULT_SIZE, 467, Short.MAX_VALUE)
                .addGap(0, 0, 0)
                .addComponent(statusBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        splitPanel.setRightComponent(mainPanel);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(splitPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 671, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(splitPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void layerTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_layerTableMouseClicked
//        Class c = CoordinateSystemAxis.class;
//        if(evt.getClickCount() == 2){
//            int row = layerTable.getSelectedRow();
//            MapLayer layer = c_model.getLayer(row);
//            Style style = JSimpleStyleDialog.showDialog(this, layer);
//            if(style != null){
//                layer.setStyle(style);
//            }
//
//        }
    }//GEN-LAST:event_layerTableMouseClicked

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MapViewer().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel demoCMZ;
    private javax.swing.JLabel demoCMZLabel;
    private javax.swing.JLabel demoCligen;
    private javax.swing.JLabel demoCligenLabel;
    private javax.swing.JLabel demoCountry;
    private javax.swing.JLabel demoCountryLabel;
    private javax.swing.JLabel demoCounty;
    private javax.swing.JLabel demoCountyLabel;
    private javax.swing.JLabel demoPosition;
    private javax.swing.JLabel demoPositionLabel;
    private javax.swing.JLabel demoState;
    private javax.swing.JLabel demoStateLabel;
    private javax.swing.JLabel demoWingen;
    private javax.swing.JLabel demoWingenLabel;
    private javax.swing.JFormattedTextField latLonField;
    private javax.swing.JTable layerTable;
    private javax.swing.JPanel mainPanel;
    private usda.weru.gis.gui.MapPane mapPane;
    private javax.swing.JPanel sidePanel;
    private javax.swing.JSplitPane splitPanel;
    private javax.swing.JPanel statusBar;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JScrollPane tableScrollPanel;
    // End of variables declaration//GEN-END:variables

    private class InternalSelectionHandler extends MouseAdapter {

        private Coordinate translate(MouseEvent e) {

            Coordinate center = c_controller.getCenter();
            double zoom = c_controller.getZoomFactor();
            double cx = e.getX() - (mapPane.getWidth() / 2);
            double cy = e.getY() - (mapPane.getHeight() / 2);
            double dx = cx / zoom;
            double dy = cy / zoom;
            return new Coordinate(center.x + dx, center.y - dy);

        }

        @Override
        public void mouseClicked(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
                Coordinate select = translate(e);
                c_controller.setCenter(select);
                LatLong latlong = GISUtil.toLatLong(select);
                setSelectedLatLong(latlong);
            } else {
                Coordinate select = translate(e);
                LatLong latlong = GISUtil.toLatLong(select);
                GISUtil.toLatLong(select);
                demoMetaData(latlong);
            }
        }

        @Override
        public void mouseExited(MouseEvent e) {
            latLonField.setValue(c_controller.getCenter());
            //demoMetaData(getSelectedLatLong());
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            Coordinate coord = translate(e);
            latLonField.setValue(coord);
            //demoMetaData(GISUtil.toLatLong(coord));
        }
    }
    DemoMetaDataSwingWorker c_demo;

    public synchronized void demoMetaData(LatLong latlong) {
        if (c_demo != null) {
            c_demo.cancel(false);
        }

        c_demo = new DemoMetaDataSwingWorker(latlong);
        c_demo.execute();

    }

    private class DemoMetaDataSwingWorker extends SwingWorker<Object, Runnable> {

        private LatLong c_latlong;

        public DemoMetaDataSwingWorker(LatLong latlong) {
            c_latlong = latlong;
        }

        @Override
        protected Object doInBackground() throws Exception {
            Thread.sleep(100);
            if (isCancelled()) {
                return null;
            }
            publish(demoCountry, "");
            publish(demoState, "");
            publish(demoCounty, "");
            publish(demoCMZ, "");
            //publish(demoSoils, "");
            publish(demoWingen, "");
            publish(demoCligen, "");

            //position
            try {
                NumberFormat format = new DecimalFormat("0.00");
                publish(demoPosition, format.format(c_latlong.longitudeValue(NonSI.DEGREE_ANGLE)) + ", " + format.format(c_latlong.latitudeValue(NonSI.DEGREE_ANGLE)));
                if (isCancelled()) {
                    return null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (isCancelled()) {
                return null;
            }
            //end position

            //territory
            List<Territory> territories = lookupValues(Territory.class);
            for (Territory territory : territories) {
                switch (territory.getType()) {
                    case Country:
                        publish(demoCountry, territory.getDisplayName());
                        break;
                    case State:
                        publish(demoState, territory.getDisplayName());
                        break;
                    case County:
                        publish(demoCounty, territory.getDisplayName());
                        publish(demoCountyLabel, territory.getTypeDescription() + ":");
                        break;
                }
            }
            if (isCancelled()) {
                return null;
            }
            //end territory

            //CMZ
            CropManagementZone cmz = lookupValue(CropManagementZone.class);
            if (cmz != null) {
                publish(demoCMZ, Float.toString(cmz.getId()));
            } else {
                publish(demoCMZ, "");
            }
            if (isCancelled()) {
                return null;
            }
            //end cmz

            //SoilMapUnit
//            SoilMapUnit mu = lookupValue(SoilMapUnit.class);
//            if (mu != null) {
//                publish(demoSoils, mu.toString());
//            } else {
//                publish(demoSoils, "");
//            }
//            if (isCancelled()) {
//                return null;
//            }
            //SoilMapUnit

            //wingen
//            WindgenSelectArea wsa = lookupValue(WindgenSelectArea.class);
//            if (wsa != null) {
//                String name = wsa.getName().toLowerCase().trim();
//                if ("out".equals(name)) {
//                    publish(demoWingen, "Out");
//                } else if ("int".equals(name)) {
//                    publish(demoWingen, "Interpolated");
//                } else {
//                    publish(demoWingen, wsa.getName());
//                }
//            } else {
//                publish(demoWingen, "");
//            }
//            if (isCancelled()) {
//                return null;
//            }
//            //end wingen
//
//            //wingen
//            CligenSelectArea csa = lookupValue(CligenSelectArea.class);
//            if (csa != null) {
//                String name = csa.getName().toLowerCase().trim();
//                if ("out".equals(name)) {
//                    publish(demoCligen, "Out");
//                } else if ("int".equals(name)) {
//                    publish(demoCligen, "Interpolated");
//                } else {
//                    publish(demoCligen, csa.getName());
//                }
//            } else {
//                publish(demoCligen, "");
//            }
//            if (isCancelled()) {
//                return null;
//            }
//            //end wingen




            return null;
        }

        private <T> T lookupValue(Class<T> type) {
            GISData data = GISData.getInstance();
            GISLookup<T> lookup = data.getLookup(type);
            List<T> results = null;
            if (lookup != null) {
                results = lookup.lookup(c_latlong);
            }

            if (results != null && !results.isEmpty()) {
                return results.get(0);
            } else {
                return null;
            }

        }

        private <T> List<T> lookupValues(Class<T> type) {
            GISData data = GISData.getInstance();
            GISLookup<T> lookup = data.getLookup(type);
            List<T> results = null;
            if (lookup != null) {
                results = lookup.lookup(c_latlong);
            }
            if (results != null) {
                return results;
            } else {
                return Collections.emptyList();
            }
        }

        private void publish(final JLabel label, final String text) {
            Runnable runnable = new Runnable() {

                @Override
                public void run() {
                    label.setText(text);
                }
            };
            publish(runnable);
        }

        @Override
        protected void process(List<Runnable> chunks) {
            for (Runnable runnable : chunks) {
                if (DemoMetaDataSwingWorker.this.isCancelled()) {
                    return;
                }
                runnable.run();
            }
        }
    }
}
