package usda.weru.weps;

import java.awt.event.ItemEvent;
import java.util.*;
import java.awt.*;
import java.beans.*;
import javax.swing.*;

/**
 * This class/object allows the US map to be viewed using the county boundaries to build the state boundaries
 * that eventually generate the map with wind and climate generation stations inserted indicated at their
 * respective locations using latitude & longitude information.
 */
public class MapViewer extends usda.weru.weps.gui.MapViewer_n implements PropertyChangeListener {

    /**
     *  Entry point for testing standalone. Used if this dialog is rum as an independent application. 
     * If executed, makes the GUI for Map Viewer visible.
     * @param args These are the command line arguments passed to the main method.
     */
    public static void main(String[] args) {

//		//System.out.println("MV_m: start loading county map");
        Vector V_state = StateMap.loadFile();
        V_state.add(0, new StateMap("none selected", "dy", "X0"));
        Vector V_county = CountyMap.loadFile(StateMap.ht);
//		//System.out.println("MV_m: finished loading county map " + V_county.size());
        Vector V_mainWinCli = WindCliStation.readWinCli(null, null);

        MapViewer mv = new MapViewer();
        DrawMap dm = new DrawMap(V_county, V_mainWinCli);
        dm.setSize(mv.JP_map.getSize());
        dm.addPropertyChangeListener(mv);
        dm.setBackground(new java.awt.Color(255, 255, 255));
        mv.JP_map.add(dm);
        mv.dm = dm;
        mv.setSize(400, 400);
        mv.setVisible(true);
//		mv.repaint();

    }

    MapViewer() {
        super();
        windowSize = getSize();
        repaint();
    }
    Dimension windowSize;
    DrawMap dm;

    /**
     * This method re-organizes the components within the container as the window size 
     * changes to accomodate the varying zoom levels on the focal points of the map.
     * @param evt The mouse or keyboard click event that changes the visible window area 
     * forcing the component resize to happen.
     */
    @Override
    protected void componentResized(java.awt.event.ComponentEvent evt) {
//		//System.out.println("MV_fCR: " + evt + " " + evt.getClass());
        Dimension newSize = getSize();
        Dimension mapSize = JP_map.getSize();
        mapSize.width += newSize.width - windowSize.width;
        mapSize.height += newSize.height - windowSize.height;
        JP_map.setSize(mapSize);
        dm.setSize(mapSize);
        dm.setClipRect(mapSize);
        Dimension toolSize = JP_tools.getSize();
        toolSize.height = mapSize.height;
        JP_tools.setSize(toolSize);
        JP_buttons.setBounds(0, mapSize.height, newSize.width, 30);
        JP_tools.invalidate();
        JP_tools.repaint();
        JP_buttons.invalidate();
        JP_buttons.repaint();
        windowSize = newSize;
    }

    /**
     * Refresh all the panels in the map viewer once the window gains focus
     * @param evt Focus gain event that helps the recognition of whether the window is currently being 
     * used.
     */
    @Override
    protected void windowGainedFocus_actionPerformed(java.awt.event.WindowEvent evt) {
        // TODO add your handling code here:
        //   //System.out.println("MapViewer:WINDOW GAINED FOCUS entered");
        this.invalidate();
        this.repaint();
        JP_map.invalidate();
        JP_map.repaint();
        JP_tools.invalidate();
        JP_tools.repaint();
        JP_buttons.invalidate();
        JP_buttons.repaint();
    }

    /**
     * Wind or climate generation station options are made visble based on the flags selected.
     * @param evt Mouse click events contributing towards change of flags.
     */
    protected void winCli_ItemStateChanged(java.awt.event.ItemEvent evt) {
//		//System.out.println("MV_wC_ISC: " + ((AbstractButton) evt.getItemSelectable()).getActionCommand() + " " + evt.getStateChange());
        if (((AbstractButton) evt.getItemSelectable()).getActionCommand().equals("wind")) {
            dm.setWinFlg(evt.getStateChange() == ItemEvent.SELECTED);
        } else {
            dm.setCliFlg(evt.getStateChange() == ItemEvent.SELECTED);
        }
    }

    private void parseLatLon(String inpVal) {
        StringTokenizer st = new StringTokenizer(inpVal, ";");
        if (st.countTokens() == 2) {
            String val = st.nextToken();
            double lon = Double.parseDouble(val);
            lon = lon / 100000;

            val = val.substring(0, val.length() - 5) + "." + val.substring(val.length() - 5);
            JL_lon.setText(val);

            val = st.nextToken();
            double lat = Double.parseDouble(val);
            lat = lat / 100000;

            val = val.substring(0, val.length() - 5) + "." + val.substring(val.length() - 5);
            JL_lat.setText(val);
        }
    }

    private String latLon = "";

    /**
     * Recognizes and takes appropriate actions on registered properties from different screens to 
     * update and synchronize data and GUI screens as needed
     * @param e The event itself that is responsible for triggering the change required for registered 
     * properties/components.
     */
    @Override
    public void propertyChange(PropertyChangeEvent e) {

        // init properties
        String inpVal = (String) e.getNewValue();
        if (e.getPropertyName().equals(RunFileData.LatLong)) {
            parseLatLon(inpVal);
            latLon = JL_lat.getText() + ";" + JL_lon.getText();
        } else if (e.getPropertyName().equals(RunFileData.Site)) {
            JL_county.setText(inpVal);
        } else if (e.getPropertyName().equals(DrawMap.StationData)) {
            JTA_stationInfo.setText(inpVal);
        } else if (e.getPropertyName().equals(DrawMap.Commit)) {
            changes.firePropertyChange(RunFileData.LatLong, null, latLon);
            setVisible(false);
        } else if (e.getPropertyName().equals(RunFileData.CliGenStationName)) {
//			JL_cli.setText(inpVal);
        } else if (e.getPropertyName().equals(RunFileData.WindGenStationName)) {
//			JL_wind.setText(inpVal);
        } else if (e.getPropertyName().equals(RunFileData.State)) {
            JL_state.setText(inpVal);
        }

    }

    /**
     * Adjust and sets the zoom level based on selection of an appropriate buttons.
     * @param evt The button click event for recognizing if things should centralized or a specific
     * area zoomed in or out.
     */
    protected void RGB_actionPerformed(java.awt.event.ActionEvent evt) {
//		//System.out.println("MV_RGB_aP: " + evt.getActionCommand());
        String cmd = evt.getActionCommand();
        if (cmd.equals("Select")) {
            dm.setButton(DrawMap.selectButton);
        } else if (cmd.equals("Center")) {
            dm.setButton(DrawMap.centerButton);
        } else if (cmd.equals("Zoom In")) {
            dm.setButton(DrawMap.zoomInButton);
        } else if (cmd.equals("Zoom Out")) {
            dm.setButton(DrawMap.zoomOutButton);
        }
    }
    private PropertyChangeSupport changes = new PropertyChangeSupport(this);

    /**
     * Allows the container to add or register some other components to recognize the changes that occur 
     * on this component
     * @param l The listener that listens and reacts towards the the changes to be reflected.
     */
    public void addPropertyChangeListener(PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }

    /**
     * Allows the container to remove or de-register some other components and stop recognizing the 
     * changes that occur on this component
     * @param l he listener that does not listen and react towards the the changes to be reflected.
     */
    public void removePropertyChangeListener(PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }
}
