import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;
import javax.imageio.ImageIO;

public class Yes {
	private static Thread _loop;
	private YesClock _clock;
	private JFrame _frame;
	private ConfigurationPanel _configuration_panel;
	private HandPanel _hand_config;
	
	public static final void main( String[] args ) {
		int sx = 500;
		int sy = 500;
		if (args.length != 0) {
			List arg_list = Arrays.asList( args );
			
			if (arg_list.contains("--size")) {
				int ind = arg_list.indexOf("--size");
				String x = (String)arg_list.get( ind+1 );
				String y = (String)arg_list.get( ind+2 );
				sx = Integer.valueOf(x).intValue();
				sy = Integer.valueOf(y).intValue();
			}

			if (arg_list.contains("--dump")) {
				int name_ind = arg_list.indexOf("--dump")+1;
				String name = (String)arg_list.get(name_ind);
				// dump
				BufferedImage i = new BufferedImage( sx, sy, BufferedImage.TYPE_INT_RGB);
				Graphics2D g = i.createGraphics();

				YesClock yesclock = new YesClock();
				Properties config = ConfigurationPanel.getConfigurationProps();
				updateBasicConfig( config, yesclock );
				yesclock.setSize( sx, sy );
				yesclock.redraw();
				yesclock.paint( g );
				File f = new File( name );
				try { ImageIO.write( i, "png", f ); }
				catch (IOException ioe) { ioe.printStackTrace(); }
				// write image here
				return;
			}
		}

		Yes y = new Yes();
		y.getFrame().setSize( new Dimension(sx,sy) );
		y.getFrame().setVisible( true );
		y.start();
	}

	public Yes() {
		_frame = new JFrame("YES");
		_frame.getContentPane().setLayout( new BorderLayout() );
		_clock = new YesClock();
		_frame.getContentPane().add( BorderLayout.CENTER, _clock );
		_frame.addWindowListener( new WindowAdapter() {
			public void windowClosing( WindowEvent we ) { exit(); }
		});

		_configuration_panel = new ConfigurationPanel( _frame );
		_hand_config = new HandPanel( _frame, this );
		updateConfiguration();

		final JPopupMenu menu = makeMenu( );
		menu.setLightWeightPopupEnabled(false);
		_clock.addMouseListener( new MouseAdapter() {
			public void mouseReleased( MouseEvent me ) {show(me);}
			public void mousePressed( MouseEvent me ) {show(me);}
			public void show( MouseEvent me ) {
				if (me.isPopupTrigger()) {
					menu.show( me.getComponent(), me.getX(), me.getY() );
				}
			}
		});
	}
	
	private void exit() {
		_loop.interrupt();
		_frame.dispose();
		System.exit(0);
	}

	protected JFrame getFrame() { return _frame; }
	
	protected void start() {
		_loop = new Thread( _clock );
		_loop.start();
	}
	
	private JPopupMenu makeMenu( ) {
		JPopupMenu menu = new JPopupMenu();
		JMenuItem item = menu.add( "Configuration..." );
		final Yes stupid_java = this;
		item.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent ae ) { 		
				_configuration_panel.expose(stupid_java);
			 } 
		});

		String def = "Change to EDT";
		if (_clock.getEDT()) def = "Change to standard";
		final JMenuItem time = menu.add( def );
		time.addActionListener( new ActionListener() {
			private String edt = "Change to EDT",
				standard = "Change to standard";
			private boolean edt_on = _clock.getEDT();
			public void actionPerformed( ActionEvent ae  ) {
				// Change the label of this menu item
				if (edt_on) {
					time.setText( edt );
					edt_on = false;
				} else {
					time.setText( standard );
					edt_on = true;
				}
				// Change the Clock to whatever it needs to be
				_clock.setEDT( edt_on );
				// Update the configuration
				_configuration_panel.getConfiguration().setProperty("edt_on", 
					String.valueOf(edt_on));
				_configuration_panel.saveConfiguration();
				// Redraw and repaint the clock.
				_clock.redraw();
				_clock.repaint();
			}
		});

		item = menu.add( "Change hand shape..." );
		item.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent ae ) {_hand_config.setVisible(true);}
		});

		item = menu.add( "About..." );
		item.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent ae ) { about(); } 
		});

		menu.addSeparator();

		item = menu.add( "Exit" );
		item.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ) { exit(); }
		});
		return menu;
	}

	protected void setHand( String hand_name ) {
		_configuration_panel.getConfiguration().setProperty( "hand_name", hand_name );
		_configuration_panel.saveConfiguration();
		updateConfiguration();
	}

	protected static void updateBasicConfig( Properties config, YesClock clock ) {
		// Get all of the preferences as Strings
		String s_lon = config.getProperty("longitude", "-121.31104");
		String s_lat = config.getProperty( "latitude", "44.06604" );
		String s_edt = config.getProperty("edt_on", "false");
		String s_tz = config.getProperty( "timezone", String.valueOf(
					(int)(Calendar.getInstance().get(Calendar.ZONE_OFFSET)/3600000)
				));
		// Set them back to the configuration
		config.setProperty( "longitude", s_lon);
		config.setProperty( "latitude", s_lat);
		config.setProperty( "timezone", s_tz);
		config.setProperty( "edt_on", s_edt);
		// Turn them all into their true value types
		float lon = Float.valueOf( s_lon ).floatValue();
		float lat = Float.valueOf( s_lat ).floatValue();
		boolean edt_on = Boolean.valueOf( s_edt ).booleanValue();
		int tz = Integer.valueOf( s_tz ).intValue();
		// Now set the clock
		clock.setLongitude( lon );
		clock.setLatitude( lat );
		clock.setEDT( edt_on );
		clock.setTZ( tz );
	}

	protected void updateConfiguration() {
		Properties config = _configuration_panel.getConfiguration();
		updateBasicConfig( config, _clock );
		String hand_name = config.getProperty( "hand_name" );
		if (hand_name != null) {
			Hand hand = _hand_config.getHand( hand_name );
			_clock.setHandLine( hand.getStroke() );
			_clock.setHandFill( hand.getFill() );
			_clock.setHand( hand.getShape() );
		}
		_clock.redraw();
		_clock.repaint();
	}
	
	private void about() {
		String version = "1.0";
		JOptionPane.showMessageDialog( _frame,
		"<HTML><H1>YesClock</H1>v"+Version.VERSION+"<BR>"+Version.DATE+"<P>"+
		Version.COPYRIGHT+"<BR>"+
		"http://www.germane-software.com/~ser<P>"+
		"For a real Yes watch, visit:<BR>http://www.yeswatch.com</HTML>",
		"About YesClock",
		JOptionPane.PLAIN_MESSAGE );
	}
}
