// PropertySelector.java
package org.eclipse.stem.ui.widgets;

/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.stem.core.graph.DynamicLabel;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.model.Decorator;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProvider;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProviderAdapter;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProviderAdapterFactory;
import org.eclipse.stem.diseasemodels.standard.DiseaseModel;
import org.eclipse.stem.jobs.simulation.ISimulation;
import org.eclipse.stem.populationmodels.standard.PopulationModel;
import org.eclipse.stem.ui.views.geographic.map.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

/**
 * This class is a compound SWT widget that allows for the selection of a
 * property or properties of one or more {@link Decorator}s.
 */
public class PropertySelector extends Composite {

	private final List<PropertySelectionListener> propertySelectionListeners = new CopyOnWriteArrayList<PropertySelectionListener>();

	private ISimulation simulation = null;

	/**
	 * This is the name of the property that should be displayed first (if
	 * possible).
	 * 
	 * @see #setPreferences()
	 */
	private String initialPropertyName;

	private final Label displayLabel;

	Combo decoratorsCombo;

	Combo propertiesCombo;

	Combo popIdsCombo;

	List<Decorator> decorators;

	Decorator selectedDecorator;

	List<ItemPropertyDescriptor> properties;

	ItemPropertyDescriptor selectedProperty;
	
	String selectedId;
	
	private DecoratorFilter decoratorFilter = new DecoratorFilter() {
		/**
		 * @see org.eclipse.stem.ui.widgets.PropertySelector.DecoratorFilter#accept(org.eclipse.stem.core.model.Decorator)
		 */
		public boolean accept(@SuppressWarnings("unused")
		Decorator decorator) {
			return true;
		}
	};

	/**
	 * The default sieve selects those properties that have relative values.
	 */
	private PropertySieve propertySieve = new PropertySieve() {
		/**
		 * @see org.eclipse.stem.ui.widgets.PropertySelector.PropertySieve#sieve(org.eclipse.stem.core.graph.DynamicLabel)
		 */
		public List<ItemPropertyDescriptor> sieve(DynamicLabel dynamicLabel) {
			final List<ItemPropertyDescriptor> retValue = new ArrayList<ItemPropertyDescriptor>();
			final RelativeValueProviderAdapter rvp = (RelativeValueProviderAdapter) RelativeValueProviderAdapterFactory.INSTANCE
					.adapt(dynamicLabel, RelativeValueProvider.class);

			// Does the label have relative values?
			if (rvp != null) {
				// Yes
				rvp.setTarget(dynamicLabel);

				for (final Object element : rvp.getProperties()) {
					final ItemPropertyDescriptor property = (ItemPropertyDescriptor) element;
					retValue.add(property);
				} // for each property
			} // if the label has relative values
			return retValue;
		} // sieve
	};

	/**
	 * @param parent
	 * @param style
	 */
	public PropertySelector(final Composite parent, final int style, boolean allowPropertySelection) {
		super(parent, style);
		final FormLayout retValueLayout = new FormLayout();
		this.setLayout(retValueLayout);

		displayLabel = new Label(this, SWT.CENTER);
		displayLabel.setText(Messages.getString("IMView.MProp") + " :"); //$NON-NLS-1$ //$NON-NLS-2$

		// Combo Box of Decorators
		decoratorsCombo = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY
				| SWT.CENTER);

		// Combo Box of the Decorator Properties
		propertiesCombo = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY
				| SWT.CENTER);

		popIdsCombo = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY 
				| SWT.CENTER);
		
		final FormData decoratorsComboFormData = new FormData();
		decoratorsComboFormData.top = new FormAttachment(displayLabel, 0);
		decoratorsComboFormData.left = new FormAttachment(0, 0);
		decoratorsComboFormData.right = new FormAttachment(100, 0);
		decoratorsCombo.setLayoutData(decoratorsComboFormData);

		final FormData propertiesComboFormData = new FormData();
		propertiesComboFormData.top = new FormAttachment(decoratorsCombo, 0);
		propertiesComboFormData.left = new FormAttachment(0, 0);
		propertiesComboFormData.right = new FormAttachment(100, 0);
		propertiesCombo.setLayoutData(propertiesComboFormData);

		final FormData popIdsComboFormData = new FormData();
		popIdsComboFormData.top = new FormAttachment(propertiesCombo, 0);
		popIdsComboFormData.left = new FormAttachment(0, 0);
		popIdsComboFormData.right = new FormAttachment(100, 0);
		popIdsCombo.setLayoutData(popIdsComboFormData);

		this.pack();

		decoratorsCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(@SuppressWarnings("unused")
			final SelectionEvent e) {
				// Any decorators?
				if (!decorators.isEmpty()) {
					// Yes
					final Decorator tempDecorator = decorators
							.get(decoratorsCombo.getSelectionIndex());
					// Was there a change in selected Decorators?
					if (selectedDecorator != tempDecorator) {
						// Yes
						selectedDecorator = tempDecorator;
						List<String> ids = getIdsToDisplay(selectedDecorator);
						selectedId = ids.get(0);
						properties = getPropertiesToDisplay(selectedDecorator, selectedId);
						selectedProperty = selectCurrentDecoratorProperty(properties);
						initializeCombo(propertiesCombo,
								getPropertyNames(properties), getPropertyIndex(
										selectedProperty, properties));
						String [] propIds = ids.toArray(new String[]{});
						initializeCombo(popIdsCombo,
								propIds, 0);

						PropertySelector.this
								.notifyPropertySelection(selectedProperty, selectedId);
					} // if Decorators changed

				} // if any decorators
			}
		} // SelectionAdapter
		);

		propertiesCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(@SuppressWarnings("unused")
			final SelectionEvent e) {
				// Any Decorator properties?
				if (!properties.isEmpty()) {
					// Yes
					// Is it different?
					final ItemPropertyDescriptor temp = properties
							.get(propertiesCombo.getSelectionIndex());
					if (selectedProperty != temp) {
						// Yes
						selectedProperty = temp;
						PropertySelector.this
								.notifyPropertySelection(selectedProperty, selectedId);
					} // if

				} // if
			} // widgetSelected

		} // SelectionAdapter
				);
		popIdsCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(@SuppressWarnings("unused")
			final SelectionEvent e) {
				List<String>ids = getIdsToDisplay(selectedDecorator);
					final String temp = ids
							.get(popIdsCombo.getSelectionIndex());
					if (!selectedId.equals(temp)) {
						// Yes
						selectedId = temp;
						properties = getPropertiesToDisplay(selectedDecorator, selectedId);
						selectedProperty = selectCurrentDecoratorProperty(properties);
						initializeCombo(propertiesCombo,
								getPropertyNames(properties), getPropertyIndex(
										selectedProperty, properties));
						PropertySelector.this
								.notifyPropertySelection(selectedProperty, selectedId);
					} // if

			} // widgetSelected

		} // SelectionAdapter
				);
		if(!allowPropertySelection)propertiesCombo.setEnabled(false);
		setSimulation(null);
	} // PropertySelector

	void notifyPropertySelection(final ItemPropertyDescriptor selectedProperty, String popid) {
		// Is there a property?
		if (selectedProperty != null) {
			// Yes
			firePropertySelectionEvent(new PropertySelectionEvent(
					selectedDecorator, selectedProperty, this,popid ));
		} // if
	} // notifyPropertySelection

	/**
	 * @return <code>true</code> if the control has been initialized.
	 */
	public boolean isInitialized() {
		return !(decorators == null || decorators.isEmpty());
	} // isInitialized

	/**
	 * @param decorators
	 */
	public void setDecorators(final List<Decorator> decorators) {
		this.decorators = decorators;
		selectedDecorator = decorators.isEmpty() ? null : decorators.get(0);
		initializeCombo(decoratorsCombo, getDecoratorNames(decorators),
				getDecoratorIndex(selectedDecorator, decorators));
		
		List<String> ids = getIdsToDisplay(selectedDecorator);
		if(ids != null) {
			String [] propIds = ids.toArray(new String[]{});
			initializeCombo(popIdsCombo,
					propIds, 0);
		}
		selectedId  = (ids==null)? null:ids.get(0);
		
		properties = getPropertiesToDisplay(selectedDecorator, selectedId);
		selectedProperty = selectCurrentDecoratorProperty(properties);
		initializeCombo(propertiesCombo, getPropertyNames(properties),
				getPropertyIndex(selectedProperty, properties));
		
		notifyPropertySelection(selectedProperty, selectedId);
	} // setDecorators

	/**
	 * Initialize the control from a
	 * {@link org.eclipse.stem.jobs.simulation.Simulation} instance.
	 * 
	 * @param simulation
	 *            the {@link org.eclipse.stem.jobs.simulation.Simulation}
	 */
	public void setSimulation(final ISimulation simulation) {
		this.simulation = simulation;
		setDecorators(getDecoratorsToDisplay(simulation));
	} // setSimulation

	/**
	 * @return the simulation
	 */
	public final ISimulation getSimulation() {
		return simulation;
	}

	/**
	 * @param decoratorFilter
	 *            the filter that determines which {@link Decorator}s will be
	 *            displayed.
	 */
	public void setDecoratorFilter(final DecoratorFilter decoratorFilter) {
		this.decoratorFilter = decoratorFilter;
	} // setDecoratorFilter

	/**
	 * @param propertySieve
	 *            the sieve that selects the properties of a {@link Decorator}
	 *            that should be displayed.
	 */
	public void setPropertySieve(final PropertySieve propertySieve) {
		this.propertySieve = propertySieve;
	} // setPropertySieve

	/**
	 * @param simulation
	 *            the simulation that contains {@link Decorator}s
	 * @return a {@link List} of the {@link Decorator}s whose properties
	 */
	private List<Decorator> getDecoratorsToDisplay(final ISimulation simulation) {
		final List<Decorator> retValue = new ArrayList<Decorator>();

		// Got Simulation?
		if (simulation != null) {
			// Yes
			final Graph canonicalGraph = simulation.getScenario()
					.getCanonicalGraph();
			// Is the canonicalGraph initialized yet?
			if (canonicalGraph != null) {
				// Yes
				// Go through the Decorators keeping the ones that the filter
				// says are ok.
				for (final Object element : canonicalGraph.getDecorators()) {
					final Decorator decorator = (Decorator) element;
					// Acceptable?
					if (decoratorFilter.accept(decorator)) {
						retValue.add(decorator);
					} // if has a title
				} // for each decorator
			} // if got graph
		} // if got simulation
		return retValue;
	} // getDecoratorsToDisplay

	/**
	 * @param decorator
	 *            a {@link Decorator} that modifies the state of the canonical
	 *            {@link Graph} in the
	 *            {@link org.eclipse.stem.jobs.simulation.Simulation}.
	 * @param simulation
	 *            the {@link org.eclipse.stem.jobs.simulation.Simulation}
	 * @return a {@link List} of the properties of the {@link Decorator} that
	 *         can should be displayed.
	 */
	List<ItemPropertyDescriptor> getPropertiesToDisplay(
			final Decorator decorator, final String populationIdentifier) {
		final List<ItemPropertyDescriptor> retValue = new ArrayList<ItemPropertyDescriptor>();
		// Got Decorator?
		if (decorator != null) {
			// Yes
			// Are there any labels to update?
			if (!decorator.getLabelsToUpdate().isEmpty()) {
				// Yes
				if (decorator instanceof DiseaseModel) {
					// Different labels exist for different populations
					retValue.addAll(propertySieve.sieve(((DiseaseModel) decorator)
							.createDiseaseModelLabel(populationIdentifier)));
				} else {
					// The first one is good enough
					retValue.addAll(propertySieve.sieve(decorator
							.getLabelsToUpdate().get(0)));
				}
			} // if labels to update
		} // if got decorator
		return retValue;
	} // getPropertiesToDisplay

	/**
	 * @param decorator
	 *            a {@link Decorator} that modifies the state of the canonical
	 *            {@link Graph} in the
	 *            {@link org.eclipse.stem.jobs.simulation.Simulation}.
	 * @return a {@link List} of the ids, e.g. population ids
	 */
	List<String> getIdsToDisplay(
			final Decorator decorator) {
		if(decorator instanceof DiseaseModel) {
			return ((DiseaseModel)decorator).getAllLabelIdentifiers();
		}
		if(decorator instanceof PopulationModel) {
			return ((PopulationModel)decorator).getAllLabelIdentifiers();
		}
		return null; // none found
	} // getPropertiesToDisplay

	// /**
	// * @param decorators
	// * the {@link Decorators} in the simulation that whose state
	// * values can be visualized.
	// * @return one of the {@link Decorators}
	// */
	// private Decorator selectCurrentDecorator(final List<Decorator>
	// decorators) {
	// return decorators.get(0);
	// } // selectCurrentDecorator

	/**
	 * @param decoratorProperties
	 *            a list of properties
	 * @return the property of the decorator that should be the one to be
	 *         displayed or <code>null</code> if decoratorProperties is empty
	 */
	ItemPropertyDescriptor selectCurrentDecoratorProperty(
			final List<ItemPropertyDescriptor> decoratorProperties) {
		// Look for a property with a name that matches the one specified in
		// the preferences.
		for (final ItemPropertyDescriptor property : decoratorProperties) {
			// name match?
			if (property.getDisplayName(property).equals(initialPropertyName)) {
				// Yes
				return property;
			} // if
		} // for each ItemPropertyDescriptor
		// Didn't find a match, just use the first one.
		// Any to use?
		if (!decoratorProperties.isEmpty()) {
			// Yes
			return decoratorProperties.get(0);
		} // if
		return null;
	} // selectCurrentDecoratorProperty

	/**
	 * @return the {@link Decorator} selected in the control, or
	 *         <code>null</code> if one is not currently selected.
	 */
	// public Decorator getSelectedDecorator() {
	// return selectedDecorator;
	// } // getSelectedDecorator
	//
	// /**
	// * @return the {@link ItemPropertyDescriptor} selected in the control, or
	// * <code>null</code> if one is not currently selected.
	// */
	// public ItemPropertyDescriptor getSelectedProperty() {
	// return selectedDecoratorProperty;
	// } // getSelectedProperty
	//
	// /**
	// * @return a display name of the selected property. This is the key to the
	// * selected relative Value
	// *
	// */
	// public String getSelectedPropertyString() {
	// String retVal = "no property selected";
	// if (selectedDecoratorProperty != null) {
	// retVal = selectedDecoratorProperty
	// .getDisplayName(selectedDecoratorProperty);
	// }
	// return retVal;
	// } // getSelectedProperty
	/**
	 * @param combo
	 * @param names
	 * @param selectionIndex
	 */
	void initializeCombo(final Combo combo, final String[] names,
			final int selectionIndex) {
		combo.setItems(names);
		combo.select(selectionIndex);
	} // initializeCombo

	/**
	 * @param decorators
	 *            a list of {@link Decorator}s
	 * @return an array of the names of the {@link Decorators}.
	 */
	private String[] getDecoratorNames(final List<Decorator> decorators) {
		final List<String> retValue = new ArrayList<String>();
		if (decorators != null) {
			// Yes
			for (final Decorator decorator : decorators) {
				final ComposedAdapterFactory itemProviderFactory = new ComposedAdapterFactory(
						ComposedAdapterFactory.Descriptor.Registry.INSTANCE);

				final IItemLabelProvider lp = (IItemLabelProvider) itemProviderFactory.adapt(
						decorator, IItemLabelProvider.class);
				String title = lp.getText(decorator);
				title = title == null ? "null" : title;
				retValue.add(title);
			} // for each decorator
		} // if
		return retValue.toArray(new String[] {});
	} // getDecoratorNames

	/**
	 * @param selectedDecorator
	 * @param decorators
	 *            a list of {@link Decorator}s.
	 * @return the position (0 origin) of the selectedDecorator in decorators,
	 *         or 0, if the decorators list is empty.
	 */
	private int getDecoratorIndex(final Decorator selectedDecorator,
			final List<Decorator> decorators) {
		if (selectedDecorator != null && decorators != null
				&& !decorators.isEmpty()) {
			// Yes
			return decorators.indexOf(selectedDecorator);
		} // if
		return 0;
	} // getDecoratorIndex

	/**
	 * @param properties
	 *            a list of {@link Decorator} properties.
	 * @return the names of the properties.
	 */
	String[] getPropertyNames(final List<ItemPropertyDescriptor> properties) {
		final List<String> retValue = new ArrayList<String>();
		if (properties != null) {
			// Yes
			for (final ItemPropertyDescriptor property : properties) {
				retValue.add(property.getDisplayName(property));
			} // for each ItemPropertyDescriptor
		} // if
		return retValue.toArray(new String[] {});
	} // getPropertyNames

	/**
	 * @param selectedDecoratorProperty
	 * @param decoratorProperties
	 * @return the index of the selectedDecoratorProperty in the
	 *         decoratorProperites list, or 0 if selectedDecoratorProperty is
	 *         <code>null</code>
	 */
	int getPropertyIndex(
			final ItemPropertyDescriptor selectedDecoratorProperty,
			final List<ItemPropertyDescriptor> decoratorProperties) {
		if (selectedDecoratorProperty != null) {
			// Yes
			return decoratorProperties.indexOf(selectedDecoratorProperty);
		} // if
		return 0;
	} // getPropertyIndex

	/**
	 * This method may be used to initialize a properties combo to display
	 * (select) a particular property
	 * 
	 * @param preferredProperty
	 *            the name of the property to display.
	 * @return <code>true</code> if the preferredProperty was found,
	 *         <code>false</code> otherwise.
	 */
	public boolean setDisplayedProperty(final String preferredProperty) {
		final int index = propertiesCombo.indexOf(preferredProperty);
		if (index >= 0) {
			propertiesCombo.select(index);
			initialPropertyName = preferredProperty;
			properties = getPropertiesToDisplay(selectedDecorator, selectedId);
			for (final ItemPropertyDescriptor property : properties) {
				// name match?
				if (property.getDisplayName(property).equals(
						initialPropertyName)) {
					// Yes
					selectedProperty = property;
					break;
				} // if
			} // for each ItemPropertyDescriptor
			firePropertySelectionEvent(new PropertySelectionEvent(
					selectedDecorator, selectedProperty, propertiesCombo, selectedId));
			return true;
		}// if selector has items
		return false;
	}// setDisplayedPropperty()

	/**
	 * @param listener
	 */
	public void addPropertySelectionListener(
			final PropertySelectionListener listener) {
		propertySelectionListeners.add(listener);
	}

	/**
	 * @param listener
	 */
	public void removePropertySelectionListener(
			final PropertySelectionListener listener) {
		propertySelectionListeners.remove(listener);
	}

	private void firePropertySelectionEvent(final PropertySelectionEvent pse) {
		for (final PropertySelectionListener listener : propertySelectionListeners) {
			listener.propertySelected(pse);
		} // for each PropertySelectionListener
	} // firePropertySelectionEvent

	/**
	 * This interface is implemented by classes that determine if a
	 * {@link Decorator} meets some specified criteria.
	 */
	public interface DecoratorFilter {
		/**
		 * @param decorator
		 * @return <code>true</code> if the {@link Decorator} is acceptable.
		 */
		boolean accept(final Decorator decorator);
	} // DecoratorFilter

	/**
	 * This interface is implemented by classes that select out the properties
	 * to be displayed.
	 */
	public interface PropertySieve {
		/**
		 * @param dynamicLabel
		 *            the label that contains the candidate properties to be
		 *            displayed.
		 * @return a <code>List</code> of the properties that should be
		 *         displayed in the order that they should be displayed.
		 */
		List<ItemPropertyDescriptor> sieve(final DynamicLabel dynamicLabel);
	} // PropertySieve

	/**
	 * This interface is implemented by classes that wish to be notified
	 * whenever a property is selected in this widget.
	 */
	public interface PropertySelectionListener {
		/**
		 * @param propertySelectionEvent
		 */
		void propertySelected(PropertySelectionEvent propertySelectionEvent);
	} // PropertySelectionListener

	/**
	 * This class represents the event of a property being selected in the
	 * widget.
	 */
	public static class PropertySelectionEvent extends EventObject {
		private static final long serialVersionUID = 1L;
		private transient final ItemPropertyDescriptor property;
		private transient final Decorator decorator;
		private transient final String id;
		
		/**
		 * @param decorator
		 *            the {@link Decorator}
		 * @param property
		 *            the property that was selected.
		 * @param source
		 */
		public PropertySelectionEvent(final Decorator decorator,
				final ItemPropertyDescriptor property, final Object source, String id) {
			super(source);
			this.decorator = decorator;
			this.property = property;
			this.id = id;
		}

		/**
		 * @return the decorator
		 */
		public final Decorator getDecorator() {
			return decorator;
		}

		/**
		 * @return the property
		 */
		public final ItemPropertyDescriptor getProperty() {
			return property;
		}

		/**
		 * getId. Get the id (e.g. population id)
		 */
		
		public String getId() {
			return id;
		}
		/**
		 * @see java.util.EventObject#toString()
		 */
		@Override
		public String toString() {
			final StringBuilder sb = new StringBuilder(
					decorator == null ? "null," : decorator.getDublinCore()
							.getTitle());
			sb.append(property == null ? "null" : property
					.getDisplayName(property));
			return sb.toString();
		}
	} // PropertySelectionEvent

	/**
	 * @return the display label
	 */
	public String getDisplayLabel() {
		return displayLabel.getText();
	}

	/**
	 * @param displayLabel
	 *            the label to display above the property selector
	 */
	public void setDisplayLabel(final String displayLabel) {
		this.displayLabel.setText(displayLabel);
	}

} // PropertySelector
