package cytoscape.visual.ui;

import static giny.view.Position.NONE;

import giny.view.ObjectPosition;
import giny.view.Position;
import giny.view.Justification;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import ding.view.ObjectPositionImpl;

public class ObjectPlacerControl extends JPanel implements ActionListener,
		PropertyChangeListener {
	
	private static final long serialVersionUID = 3875032897986523443L;
	
	private ObjectPosition lp;
	private JComboBox justifyCombo;
	private JTextField xoffsetBox;
	private JTextField yoffsetBox;
	private JComboBox nodeAnchors;
	private JComboBox labelAnchors;
	private boolean ignoreEvents;

	public ObjectPlacerControl(final ObjectPosition pos) {
		super();

		if (pos == null)
			lp = new ObjectPositionImpl();
		else
			lp = pos;

		ignoreEvents = false;

		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

		JPanel anchorNames = new JPanel();
		anchorNames.setLayout(new GridLayout(2, 2));

		final String[] points = Position.getNames();

		JLabel nodeAnchorLabel = new JLabel("Node Anchor Points ");
		nodeAnchors = new JComboBox(points);
		nodeAnchors.addActionListener(this);
		anchorNames.add(nodeAnchorLabel);
		anchorNames.add(nodeAnchors);

		JLabel labelAnchorLabel = new JLabel("Object Anchor Points");
		labelAnchors = new JComboBox(points);
		labelAnchors.addActionListener(this);
		anchorNames.add(labelAnchorLabel);
		anchorNames.add(labelAnchors);

		add(anchorNames);

		JPanel justifyPanel = new JPanel();
		justifyPanel.setLayout(new GridLayout(1, 2));

		JLabel justifyLabel = new JLabel("Label Justification");
		final String[] justifyTypes = Justification.getNames();
		justifyCombo = new JComboBox(justifyTypes);
		justifyCombo.addActionListener(this);
		justifyPanel.add(justifyLabel);
		justifyPanel.add(justifyCombo);

		add(justifyPanel);

		JPanel offsetPanel = new JPanel();
		offsetPanel.setLayout(new GridLayout(2, 2));

		JLabel xoffsetLabel = new JLabel("X Offset Value (can be negative)");
		xoffsetBox = new JTextField("0", 8);
		xoffsetBox.addActionListener(this);
		offsetPanel.add(xoffsetLabel);
		offsetPanel.add(xoffsetBox);

		JLabel yoffsetLabel = new JLabel("Y Offset Value (can be negative)");
		yoffsetBox = new JTextField("0", 8);
		yoffsetBox.addActionListener(this);
		offsetPanel.add(yoffsetLabel);
		offsetPanel.add(yoffsetBox);

		add(offsetPanel);

		applyPosition();
	}

	private void applyPosition() {
		ignoreEvents = true; // so that we don't pay attention to events
								// generated from these calls

		Position nodeAnchor = lp.getTargetAnchor();
		Position labelAnchor = lp.getAnchor();

		if (nodeAnchor.equals(NONE))
			nodeAnchors.setSelectedIndex(-1);
		else
			nodeAnchors.setSelectedItem(nodeAnchor.getName());
		
		if (labelAnchor.equals(NONE))
			labelAnchors.setSelectedIndex(-1);
		else
			labelAnchors.setSelectedItem(labelAnchor.getName());

		justifyCombo.setSelectedItem(lp.getJustify().getName());
		xoffsetBox.setText(new Integer((int) lp.getOffsetX()).toString());
		yoffsetBox.setText(new Integer((int) lp.getOffsetY()).toString());
		ignoreEvents = false;
		repaint();
	}

	/**
	 * DOCUMENT ME!
	 * 
	 * @param e
	 *            DOCUMENT ME!
	 */
	public void actionPerformed(ActionEvent e) {
		// ignore events that are generated by setting values to match
		// the graphic
		if (ignoreEvents)
			return;

		Object source = e.getSource();
		boolean changed = false;

		if (source == nodeAnchors) {
			lp.setTargetAnchor(Position.parse(nodeAnchors.getSelectedItem()
					.toString()));
			changed = true;
		}

		if (source == labelAnchors) {
			lp.setAnchor(Position.parse(labelAnchors.getSelectedItem()
					.toString()));
			changed = true;
		}

		if (source == justifyCombo) {
			lp.setJustify(Justification.parse(justifyCombo.getSelectedItem()
					.toString()));
			changed = true;
		}

		// handle both at the same time since people might forget to press enter
		if ((getOffset(xoffsetBox) != lp.getOffsetX())
				|| (getOffset(yoffsetBox) != lp.getOffsetY())) {
			lp.setOffsetX(getOffset(xoffsetBox));
			lp.setOffsetY(getOffset(yoffsetBox));
			changed = true;
		}

		if (!changed)
			return; // nothing we care about has changed

		firePropertyChange(ObjectPlacerGraphic.OBJECT_POSITION_CHANGED, null,
				lp);
	}

	private double getOffset(JTextField jtf) {
		try {
			double d = Double.parseDouble(jtf.getText());

			return d;
		} catch (Exception ex) {
			jtf.setText("0");
			return 0.0;
		}
	}

	/**
	 * DOCUMENT ME!
	 * 
	 * @param e
	 *            DOCUMENT ME!
	 */
	public void propertyChange(PropertyChangeEvent e) {
		String type = e.getPropertyName();

		if (type.equals(ObjectPlacerGraphic.OBJECT_POSITION_CHANGED)
				&& e.getNewValue() instanceof ObjectPosition) {
			lp = (ObjectPosition) e.getNewValue();
			applyPosition();
		}
	}
}
