import javax.swing.*;
import java.util.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.tree.*;

public class ConfigurationPanel extends JDialog implements myoPyx.Listener, Observer {
	private Properties _configuration;
	private static final File PROPS_FILE =
	    new File(System.getProperty("user.home"), ".YesClock");
	private JTextField _latitude, _longitude, _timezone;
	private Hashtable _contents = null;
	private JLabel _message;
	private Yes _callback;

	public ConfigurationPanel( JFrame c ) {
		super(c, "Configuration" );
		// Create properties file, load if exists
		_configuration = getConfigurationProps();
		loadCities();

		// **********************************
		// Here create the location selection
		// Add some widgets here...
		JTree tree = new JTree(_contents);
		tree.addTreeSelectionListener( new TreeSelectionListener() {
			public void valueChanged( TreeSelectionEvent e ) {
				TreePath path = e.getNewLeadSelectionPath();
				if (path == null) return;
				Object uobject = ((DefaultMutableTreeNode)path.
					getLastPathComponent()).getUserObject();
				if (uobject instanceof City ) {
					City city = (City)uobject;
					_longitude.setText( city.longitude );
					_longitude.setBackground(Color.white);
					_latitude.setText( city.latitude );
					_latitude.setBackground(Color.white);
					_timezone.setText( city.timezone );
					_timezone.setBackground(Color.white);
				}
			}
		});

		JLabel instructions =
		    new JLabel("<html>Select the city closest to you from the "+
						"list to the left, or click on your location on the "+
						"map below, or set your Longitude and Latitude by "+
						"entering the values in the text areas below.  "+
						"Note that using the map below will not set your timezone. "+
						"Check the timezone; it is set by default from your operating "+ 
						"system, but it may be wrong."+
						"</html>" );
		MapPanel map = new MapPanel();
		map.addObserver(this);
		_message = new JLabel("");
		_longitude = new JTextField();
		JPanel p1 = new JPanel();
		p1.setLayout( new BorderLayout() );
		p1.setBorder( new TitledBorder(new EtchedBorder(), "Longitude"));
		p1.add( _longitude, BorderLayout.CENTER );

		_latitude = new JTextField();
		JPanel p2 = new JPanel();
		p2.setLayout( new BorderLayout() );
		p2.setBorder( new TitledBorder( new EtchedBorder(), "Latitude" ));
		p2.add( _latitude, BorderLayout.CENTER );

		_timezone = new JTextField();
		JPanel p3 = new JPanel();
		p3.setLayout( new BorderLayout() );
		p3.setBorder( new TitledBorder( new EtchedBorder(), "Timezone" ));
		p3.add( _timezone, BorderLayout.CENTER );


		// ************************************
		// Here create the buttons
		final JDialog stupid_java = this;
		// Add a "Save" button that calls saveConfiguration and closes this
		JButton save = new JButton( "Save" );
		save.addActionListener( new ActionListener() {
			                        public void actionPerformed( ActionEvent ae ) {
										// Get the values from the widgets, place in _configuration
										JTextField c=null;
										try {
											// Validate the widget values
											c = _latitude;
											Float.valueOf(c.getText());
											c = _longitude;
											Float.valueOf(c.getText());
											c = _timezone;
											Integer.valueOf(c.getText());
											clear();
											// Put the widget values into the configuration
											widgetsToConfig();
											saveConfiguration();
											_callback.updateConfiguration();
											stupid_java.setVisible( false );
										} catch (Exception e) {
											_message.setText("<HTML><H2><COLOR='#F00'>Bad number "+
												"format!</COLOR></H2></HTML>");
											c.setBackground(Color.red);
										}
									}
		});
		// Add a "Cancel" button that closes
		JButton cancel = new JButton( "Cancel" );
		cancel.addActionListener( new ActionListener() {
			                          public void actionPerformed( ActionEvent ae ) {
				                          // revert values;
																	configToWidgets();
																	clear();
				                          stupid_java.setVisible( false );
			                          }
		                          });

		Box rbot = Box.createVerticalBox();
		rbot.add(map);
		rbot.add(_message);
		rbot.add(p1);
		rbot.add(p2);
		rbot.add(p3);
		
		JPanel right = new JPanel();
		right.setLayout( new BorderLayout() );
		right.add( instructions, BorderLayout.CENTER );
		right.add( rbot, BorderLayout.SOUTH );
		
		Box buttonbox = Box.createHorizontalBox();
		buttonbox.add(save);
		buttonbox.add(cancel);

		JSplitPane locationbox = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
		locationbox.setLeftComponent(new JScrollPane(tree));
		locationbox.setRightComponent(right);
		locationbox.setResizeWeight( 0.50 );

		getContentPane().setLayout( new BorderLayout() );
		getContentPane().add( locationbox, BorderLayout.CENTER );
		getContentPane().add( buttonbox, BorderLayout.SOUTH );
		pack();
		setSize( 640, 600 );
	}

	private void clear() {
		_message.setText("");
		_latitude.setBackground(Color.white);
		_longitude.setBackground(Color.white);
		_timezone.setBackground(Color.white);
	}

	private void widgetsToConfig() {
		_configuration.setProperty("latitude", _latitude.getText() );
		_configuration.setProperty("longitude", _longitude.getText() );
		_configuration.setProperty("timezone", _timezone.getText() );
	}

	private void configToWidgets() {
		_latitude.setText( _configuration.getProperty("latitude") );
		_longitude.setText( _configuration.getProperty("longitude") );
		_timezone.setText( _configuration.getProperty("timezone") );
	}

	public static Properties getConfigurationProps(){
		try {
			Properties configuration = new Properties();
			if (PROPS_FILE.exists()) {
				InputStream in = new FileInputStream( PROPS_FILE );
				configuration.load(in);
				in.close();
			}
			return configuration;
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return null;
	}

	public Properties getConfiguration() { return _configuration; }
	
	public void expose( Yes y ) {
		_callback = y;
		configToWidgets();
		setVisible( true );
	}

	public void saveConfiguration() {
		// Write the configuration out. Notify the callback object when done,
		// so the application can use the new settings.
		try {
			OutputStream out = new FileOutputStream(PROPS_FILE);
			_configuration.store( out, "YES Clock configuration file" );
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void update( Observable o, Object arg ) {
		_latitude.setText( String.valueOf(((MapPanel.Location)arg).lat) );
		_longitude.setText( String.valueOf(((MapPanel.Location)arg).lon) );
	}
	
	public static final void main( String[] args ) {
		JFrame frame = new JFrame( "Test" );
		ConfigurationPanel p = new ConfigurationPanel( frame );
		p.pack();
		p.setVisible( true );
	}
	private void loadCities() {
		myoPyx p = new myoPyx();
		p.addListener( null, this );
		Reader r = new InputStreamReader(ClassLoader.getSystemResourceAsStream( "cities.pyx" ));
		try {
			p.parse(r);
		} catch( Exception e ) {
			e.printStackTrace();
		}
	}
	
	private String _continent, _region;
	public void startElement( String name, HashMap attributes ) {
		if (name.equals("Continent") ) {
			_continent = (String)attributes.get("name");
			_contents.put( _continent, new Hashtable() );
		} else if (name.equals("Region")) {
			_region = (String)attributes.get("name");
			((Hashtable)_contents.get(_continent)).put( _region, new Hashtable() );
		} else if (name.equals("City")) {
			Hashtable h = (Hashtable)_contents.get(_continent);
			if (_region != null) h = (Hashtable)h.get(_region);
			h.put( new City( attributes ), "" );
		} else if (name.equals("Cities")) {
			_contents = new Hashtable();
		}
	}
	public void endElement( String name ) {
		if (name.equals("Region")) _region = null;
		if (name.equals("Continent")) _continent = null;
	}
	public void text( String text ) { }

	private class City {
		public String name, latitude, longitude, timezone;
		public City( HashMap props ) {
			name = (String)props.get("name");
			latitude = (String)props.get("lat");
			longitude = (String)props.get("lon");
			timezone = (String)props.get("tz");
		}
		public String toString() {
			return name;
		}
	}
}
