import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;

public class HandPanel extends JDialog implements myoPyx.Listener {
	private HashMap _shapes;
	private static final File USERFILE = new File(
	    System.getProperty("user.home"), ".YesClockHands"
		);
	private Yes _callback;
	private JList _list;

	public HandPanel( JFrame f, Yes callback ) {
		super( f, "Hand shape configuration" );
		_callback = callback;
		_shapes = new HashMap();
		_list = new JList(_shapes.keySet().toArray());
		loadHands( ClassLoader.getSystemResourceAsStream( "hands.pyx" ) );
		ActionListener load_hands = new ActionListener() {
			public void actionPerformed( ActionEvent ae ) { 
				try {
					loadHands( new FileInputStream( USERFILE ));
					repaint();
				} catch (Exception e) {
					// If this happens, the file just probably doesn't exist
				}
			}
		};
		load_hands.actionPerformed( null );

		_list.setCellRenderer( new ShapeRenderer( _shapes ) );
		JScrollPane scroll = new JScrollPane(_list);
		getContentPane().setLayout( new BorderLayout() );
		getContentPane().add( scroll, BorderLayout.CENTER );
		
		JButton save = new JButton("Save");
		save.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent ae ) { save(); }
		});
		JButton cancel = new JButton("Cancel");
		cancel.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent ae ) { cancel(); }
		});
		JButton reload = new JButton("Reload");
		reload.addActionListener( load_hands );
		
		Box buttonbox = Box.createHorizontalBox();
		getContentPane().add( buttonbox, BorderLayout.SOUTH );
		buttonbox.add( save );
		buttonbox.add( reload );
		buttonbox.add( cancel );
		pack();
		setSize( 250, 400 );
	}

	public Hand getHand( String name ) { 
		return (Hand)_shapes.get(name);
	}

	private void loadHands( InputStream in ) {
		Reader r = new InputStreamReader( in );
		myoPyx p = new myoPyx();
		p.addListener( null, this );
		try {
			p.parse(r);
		} catch (Exception e) {
			e.printStackTrace();
		}
		_list.setListData( _shapes.keySet().toArray() );
	}

	private boolean modelContains( ListModel m, Object k ) {
		for (int x=0; x<m.getSize(); x++) {
			if (m.getElementAt(x).toString().equals( k.toString() )) return true;
		}
		return false;
	}

	private void save() {
		if (_list.getSelectedValue() == null) return;
		_callback.setHand( _list.getSelectedValue().toString() );
		this.setVisible( false );
	}

	private void cancel() {
		this.setVisible( false );
	}

	private String _name;
	private ArrayList _lines;
	public void startElement( String name, HashMap attrs ) {
		if (name.equals("hand")) {
			_name = (String)attrs.get("name");
			_lines = new ArrayList();
		}
	}
	public void text( String text ) { 
		_lines.add( text );
	}
	public void endElement( String name ) {
		// The next five lines are because Java is a crap language designed by
		// a bunch of talking, flea-bitten monkeys.
		int ctr = 0;
		String[] lines = new String[ _lines.size() ];
		for (Iterator i=_lines.iterator(); i.hasNext(); ) {
			lines[ctr++] = i.next().toString();
		}
		Hand h = new Hand( lines );
		_shapes.put( _name, h );
	}
}

class ShapeRenderer extends JComponent implements ListCellRenderer {
	private HashMap _shapes;
	private Hand _current;
	private static final int 
		D = 100,	// Dimension for w*h
		C = D/2;	// Center
	private static final float S = (float)D/(float)(D*2);	// Scaling factor
	private static final float OOS = 1.0f / S;
	private boolean _is_selected;
	private HashMap _hints;
	private Stroke _thick, _thin;
	private String _name;

	public ShapeRenderer( HashMap shapes ) {
		_shapes = shapes;
		setSize( D, D );
		_hints = new HashMap();
		_hints.put( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
		_thick = new BasicStroke( 4, BasicStroke.CAP_BUTT
		, BasicStroke.JOIN_BEVEL );
		_thin = new BasicStroke( 2, BasicStroke.CAP_BUTT
		, BasicStroke.JOIN_BEVEL );
	}

	public Component getListCellRendererComponent(
			JList list,
			Object value,            // value to display
			int index,
			boolean isSelected,
			boolean cellHasFocus)
	{
		_name = value.toString();
		_current = (Hand)_shapes.get(_name);
		_is_selected = isSelected;
		return this;
	}
	public void paint( Graphics g ) {
		Graphics2D g2 = (Graphics2D)g;
		g2.addRenderingHints( _hints );
		if (_is_selected) g2.setPaint( Color.red );
		else g2.setPaint( Color.blue );
		g2.setStroke( _thick );
		g2.drawRect(0,0, D-4, D-4);
		g2.setStroke( _thin );
		g2.translate( C, C );
		g2.scale( S,S );
		Shape s = _current.getShape();
		g2.setPaint( _current.getStroke() );
		g2.draw( s );
		g2.setPaint( _current.getFill() );
		g2.fill( s );
		g2.scale( OOS,OOS );
		g2.drawString( _name, C, 0 );
	}
	public Dimension getPreferredSize() {
		return new  Dimension( D, D );
	}
}
