package net.sf.taverna.t2.lang.uibuilder;

import static net.sf.taverna.t2.lang.uibuilder.Icons.getIcon;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

/**
 * Superclass for list and wrapped list components generated by the UI builder.
 * Accepts properties to determine whether the 'new', 'move' and 'delete'
 * controls should be displayed and what, if any, concrete class should be used
 * when constructing new items. Properties are as follows:
 * <p>
 * <ul>
 * <li><code>nodelete</code> If set do not show the 'delete item' button</li>
 * <li><code>nomove</code> If set do not show the 'move up' and 'move down'
 * buttons</li>
 * <li><code>new=some.class.Name</code> If set then use the specified class,
 * loaded with the target object's classloader, when adding new items. Also adds
 * the 'New Item' button to the top of the list panel. The specified class must
 * be valid to insert into the list and must have a no-argument constructor</li>
 * </ul>
 * 
 * @author Tom Oinn
 * 
 */
public abstract class AbstractListComponent extends JPanel {

	private static final long serialVersionUID = 2067559836729348490L;

	private static Logger logger = Logger
	.getLogger(AbstractListComponent.class);

	private String fieldName;
	@SuppressWarnings("unchecked")
	private List theList;
	private Properties props;
	private Map<String, Properties> fieldProps;
	private List<String> subFields;
	private String parent;
	private JPanel listItemContainer;
	private boolean showDelete = true;
	private boolean showMove = true;
	@SuppressWarnings("unchecked")
	private Class newItemClass = null;
	protected static Color deferredButtonColour = Color.orange;
	private static Object[] prototypes;

	static {
		try {
			prototypes = new Object[] { new URL("http://some.host.com/path"),
					new Boolean(true), new Integer(1), new Float(1),
					new Short((short) 1), new Long((long) 1),
					new Character('a'), new Double((double) 1),
					new Byte((byte) 1) };
		} catch (MalformedURLException e) {
			logger.error("Unable to generate URL", e);
		}
	}

	/**
	 * Build a generic list component
	 * 
	 * @param fieldName
	 *            the name of the field this component represents in its parent
	 *            bean
	 * @param theList
	 *            the list value of the field
	 * @param props
	 *            properties for this field
	 * @param fieldProps
	 *            aggregated properties for all fields in the UI builder scope
	 * @param newItemClass
	 *            the class to use for construction of new item instances, or
	 *            null if this is not supported
	 * @param subFields
	 *            all field names within this field, this will be empty for a
	 *            wrapped list
	 * @param parent
	 *            the parent field ID used to access subfield properties
	 * @throws NoSuchMethodException
	 * @throws ClassNotFoundException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	@SuppressWarnings("unchecked")
	protected AbstractListComponent(String fieldName, List theList,
			Properties props, Map<String, Properties> fieldProps,
			final Class<?> newItemClass, List<String> subFields, String parent)
			throws NoSuchMethodException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException,
			ClassNotFoundException {
		super();
		this.fieldName = fieldName;
		this.theList = theList;
		this.props = props;
		this.fieldProps = fieldProps;
		this.subFields = subFields;
		this.parent = parent;
		if (props.containsKey("nodelete")) {
			showDelete = false;
		}
		if (props.containsKey("nomove")) {
			showMove = false;
		}
		this.newItemClass = newItemClass;
		setOpaque(false);
		setLayout(new BorderLayout());
		String displayName = fieldName;
		if (props.containsKey("name")) {
			displayName = props.getProperty("name");
		}
		setBorder(BorderFactory.createTitledBorder(displayName));
		if (newItemClass != null) {
			// Generate 'add new' UI here
			JPanel newItemPanel = new JPanel();
			newItemPanel.setOpaque(false);
			newItemPanel.setLayout(new BoxLayout(newItemPanel,
					BoxLayout.LINE_AXIS));
			newItemPanel.add(Box.createHorizontalGlue());

			final JButton newItemButton = new JButton("New Item",
					getIcon("new"));
			newItemPanel.add(newItemButton);
			newItemButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					try {
						Object instance = null;
						try {
							instance = newItemClass.newInstance();
						} catch (InstantiationException ie) {
							// Probably because the class has no default
							// constructor, use the prototype list
							for (Object prototype : prototypes) {
								if (newItemClass.isAssignableFrom(prototype
										.getClass())) {
									instance = prototype;
									break;
								}
							}
							if (instance == null) {
								throw ie;
							}
						}
						addNewItemToList(instance);
						newItemButton.setForeground(BeanComponent.validColour);
					} catch (Exception ex) {
						newItemButton
								.setForeground(BeanComponent.invalidColour);
						logger.error("", ex);
					}
				}
			});
			add(newItemPanel, BorderLayout.NORTH);
		}
		listItemContainer = new JPanel();
		listItemContainer.setOpaque(false);
		listItemContainer.setLayout(new BoxLayout(listItemContainer,
				BoxLayout.PAGE_AXIS));
		updateListContents();
		add(listItemContainer, BorderLayout.CENTER);
	}

	protected void updateListContents() throws NoSuchMethodException,
			IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, ClassNotFoundException {
		listItemContainer.removeAll();
		boolean first = true;
		int index = 0;
		List<JComponent> listComponents = getListComponents();
		for (JComponent component : listComponents) {
			if (first && newItemClass == null) {
				first = false;
			} else {
				List<Component> c = getSeparatorComponents();
				if (c != null) {
					for (Component jc : c) {
						listItemContainer.add(jc);
					}
				}
			}
			JComponent wrappedComponent = wrapWithControls(component, index++,
					listComponents.size());
			if (wrappedComponent != null) {
				listItemContainer.add(wrappedComponent);
			} else {
				listItemContainer.add(component);
			}
		}
		revalidate();
	}

	/**
	 * Wrap the given component in a panel including whatever list manipulation
	 * controls are needed. The index of the item being wrapped is supplied to
	 * inform the various actions the controls can perform. By default this
	 * returns a JPanel with delete and move controls
	 * 
	 * @param component
	 * @param index
	 * @return
	 */
	protected JPanel wrapWithControls(JComponent component, final int index,
			int listSize) {
		int numberOfButtons = 3;
		if (!showDelete) {
			numberOfButtons--;
		}
		if (!showMove) {
			numberOfButtons -= 2;
		}
		if (numberOfButtons == 0) {
			return null;
		}
		JPanel result = new JPanel();
		result.setOpaque(false);
		result.setLayout(new BorderLayout());
		result.add(component, BorderLayout.CENTER);
		// Construct the controls
		JPanel controls = new JPanel();
		controls.setOpaque(false);
		controls.setLayout(new BorderLayout());
		controls
				.add(new JSeparator(SwingConstants.VERTICAL), BorderLayout.WEST);
		result.add(controls, BorderLayout.EAST);
		JPanel buttons = new JPanel();
		buttons.setOpaque(false);
		buttons.setLayout(new GridLayout(0, numberOfButtons));

		if (showMove) {
			// Move up button, or spacer if already at index 0
			if (index > 0) {
				JButton moveUpButton = createButton("up", false);
				moveUpButton.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						try {
							itemMoved(index, index - 1);
						} catch (Exception ex) {
							logger.error("Unable to move item", ex);
						}
					}
				});
				buttons.add(moveUpButton);
			} else {
				buttons.add(Box.createGlue());
			}

			// Move down button, or spacer if index == listSize-1
			if (index < (listSize - 1)) {
				JButton moveDownButton = createButton("down", false);
				moveDownButton.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						try {
							itemMoved(index, index + 1);
						} catch (Exception ex) {
							logger.error("Unable to move item", ex);
						}
					}
				});
				buttons.add(moveDownButton);
			} else {
				buttons.add(Box.createGlue());
			}
		}

		if (showDelete) {
			// Delete button
			JButton deleteButton = createButton("delete", true);
			deleteButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					try {
						deleteItemAtIndex(index);
					} catch (Exception ex) {
						logger.error("Unable to delete item", ex);
					}
				}
			});
			buttons.add(deleteButton);
		}
		JPanel buttonWrapper = new JPanel();
		buttonWrapper.setLayout(new BorderLayout());
		buttonWrapper.setOpaque(false);
		buttonWrapper.add(buttons, BorderLayout.NORTH);
		controls.add(buttonWrapper, BorderLayout.CENTER);
		return result;
	}

	private static Timer timer = new Timer();

	@SuppressWarnings("serial")
	private JButton createButton(String iconName, final boolean deferActions) {
		JButton result = new JButton(getIcon(iconName)) {
			@Override
			public Dimension getPreferredSize() {
				return new Dimension(getIcon().getIconWidth() + 8, (int) super
						.getPreferredSize().getHeight());
			}

			@Override
			public Dimension getMinimumSize() {
				return new Dimension(getIcon().getIconWidth() + 8, (int) super
						.getMinimumSize().getHeight());
			}

			private boolean active = false;
			private Color defaultBackground = null;

			@Override
			public void addActionListener(final ActionListener theListener) {
				if (defaultBackground == null) {
					defaultBackground = getBackground();
				}
				if (!deferActions) {
					super.addActionListener(theListener);
					return;
				} else {
					super.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent ae) {
							if (active) {
								theListener.actionPerformed(ae);
							} else {
								setActive(true);
								timer.schedule(new TimerTask() {

									@Override
									public void run() {
										SwingUtilities
												.invokeLater(new Runnable() {
													public void run() {
														setActive(false);
													}
												});
									}
								}, 1000);
							}
						}
					});
				}
			}

			private synchronized void setActive(boolean isActive) {
				if (isActive == active) {
					return;
				} else {
					active = isActive;
					setBackground(active ? deferredButtonColour
							: defaultBackground);

				}
			}
		};
		result.setFocusable(false);
		return result;
	}

	/**
	 * Called when building the UI, must return a list of editor components
	 * corresponding to items in the list
	 * 
	 * @throws NoSuchMethodException
	 * @throws ClassNotFoundException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	protected abstract List<JComponent> getListComponents()
			throws NoSuchMethodException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException,
			ClassNotFoundException;

	/**
	 * Override to specify a separator component to be used inbetween internal
	 * list components, by default no component is used (this returns null).
	 * 
	 * @return
	 */
	protected List<Component> getSeparatorComponents() {
		return null;
	}

	/**
	 * Called when the user has clicked on the 'new item' button, this method is
	 * passed the new instance of the specified type and should handle the
	 * addition of this item to the list and the update of the UI to reflect
	 * this change
	 * 
	 * @param o
	 *            the object to add to the list
	 * @throws ClassNotFoundException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 */
	protected abstract void addNewItemToList(Object o)
			throws IllegalArgumentException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException,
			ClassNotFoundException;

	/**
	 * Called when the user has clicked on the 'delete item' button next to a
	 * particular item in the list, this method is passed the index within the
	 * list of the item to be deleted and must update the UI appropriately
	 * 
	 * @param index
	 * @throws ClassNotFoundException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 */
	protected abstract void deleteItemAtIndex(int index)
			throws IllegalArgumentException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException,
			ClassNotFoundException;

	/**
	 * Called when the user has moved an item from one index to another, passed
	 * the old index of the item and the desired new index. This method must
	 * effect the actual move within the list and the update of the UI.
	 * 
	 * @throws ClassNotFoundException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 */
	protected abstract void itemMoved(int fromIndex, int toIndex)
			throws IllegalArgumentException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException,
			ClassNotFoundException;

	/**
	 * Get the field name of this component
	 * 
	 * @return
	 */
	protected final String getFieldName() {
		return this.fieldName;
	}

	/**
	 * Return the underlying list presented by this component
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected final List getUnderlyingList() {
		return this.theList;
	}

	/**
	 * Get a list of (renamed) sub-fields of this field, so if this field was
	 * foo.bar.someList and had a foo.bar.someList.urgle this would contain
	 * 'urgle'
	 * 
	 * @return
	 */
	protected final List<String> getSubFields() {
		return this.subFields;
	}

	/**
	 * Get the properties applied to this list component
	 * 
	 * @return
	 */
	protected final Properties getProperties() {
		return this.props;
	}

	/**
	 * The parent field name is the name of this field plus its parent string
	 * and is used when recursively building sub-panels within the list. Pass
	 * this into the 'parent' argument of the UIBuilder's construction methods.
	 * 
	 * @return
	 */
	protected final String getParentFieldName() {
		return this.parent;
	}

	/**
	 * Get the map of all field->property object block defined by the UI builder
	 * constructing this component. This is used along with the parent field
	 * name to determine properties of sub-components when recursing into a
	 * nested collection.
	 * 
	 * @return
	 */
	protected final Map<String, Properties> getFieldProperties() {
		return this.fieldProps;
	}

}
