// IntensityColorsLabelsMappingColorProviderAdapter.java
package org.eclipse.stem.ui.adapters.color;

/*******************************************************************************
 * 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.awt.AlphaComposite;
import java.util.ConcurrentModificationException;
import java.util.Map;

import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.stem.core.graph.DynamicNodeLabel;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabel;
import org.eclipse.stem.populationmodels.standard.PopulationModel;
import org.eclipse.stem.populationmodels.standard.PopulationModelLabel;
import org.eclipse.stem.ui.adapters.color.AbstractRelativeValueColorProviderAdapterFactory.PropertySelectionListener;
import org.eclipse.stem.ui.preferences.VisualizationPreferencePage;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;

/**
 * This class adapts {@link Node} objects to
 * {@link IntensityColorsLabelsMappingColorProvider} object.
 */
public class IntensityColorsLabelsMappingColorProviderAdapter extends
		AbstractRelativeValueColorProviderAdapter implements PropertySelectionListener{
	/**
	 * default {@link AlphaComposite}
	 */
	//private static final AlphaComposite ONE_COMPOSITE = makeComposite(1);
	private final Map<String, STEMColor> colorMap = VisualizationPreferencePage.getColorMapping();
	private ItemPropertyDescriptor selectedProperty;

	/**
	 *  Constructor
	 */
	public IntensityColorsLabelsMappingColorProviderAdapter() {
		super();
	} // IntensityColorsLabelsMappingColorProviderAdapter

	/**
	 * @see org.eclipse.stem.ui.adapters.color.AbstractRelativeValueColorProviderAdapter#getRelativeValue()
	 */
	@Override
	public float getRelativeValue() {
		
		final Node node = (Node) getTarget();
		try {
			for (final NodeLabel label : node.getLabels()) {
				if (label instanceof DynamicNodeLabel) {
					DynamicNodeLabel nodeLabel = (DynamicNodeLabel)label;
					if (nodeLabel.getDecorator() == selectedDecorator) {
						
						if(selectedDecorator instanceof DiseaseModel) {
							if(nodeLabel instanceof DiseaseModelLabel) {
								if(!((DiseaseModelLabel)nodeLabel).getPopulationModelLabel().getPopulationIdentifier().equals(selectedPopulationIdentifier)) {
									continue; // wrong population identifier
								} else {
									setRVPTarget(nodeLabel);
									return (float) rvp.getRelativeValue(selectedProperty);
								}			
							}// if disease model label
						} // if disease model
					
						if(selectedDecorator instanceof PopulationModel) {
							String popId = selectedPopulationIdentifier;
							if(nodeLabel instanceof PopulationModelLabel) {
								if(! ((PopulationModelLabel)nodeLabel).getPopulationIdentifier().equals(popId)) {
									continue; // wrong population identifier
								} else {
									setRVPTarget(nodeLabel);
									return (float) rvp.getRelativeValue(selectedProperty);
								}	
							}// if population model label
						}// if population model
						
					}// if selected
				}// if dynamic label
			}// for all labels
		} catch(ConcurrentModificationException cme) {
			// We expect exception to be rare so we simply retry the getRelativeValue call
			return getRelativeValue();
		}

		return 0; // We shouldn't reach this point
	} // getRelativeValue

	
	
	public STEMColor getColor(final float gainFactor, final boolean useLogScaling)
	{
		final String selectedPropertyName = selectedProperty.getDisplayName(null);

		// Get the color for the selected property (label)
		if (colorMap.containsKey(selectedPropertyName)) {
			foregroundFillColor = colorMap.get(selectedPropertyName);
		} else {
			// check for complex compartment names and add those to the map if necessary
			// this way we avoid lots of future string manipulation when we want to find the colors
			// Check for a prefix match
						for (String key : colorMap.keySet()) {
							if((selectedPropertyName.startsWith(key))&&(key.length()>=1)) {
								// might be right
								String tail = selectedPropertyName.substring(key.length(), selectedPropertyName.length());
								//if perfect match (should not happen)
								if((tail==null)||(tail.length()==0)) {
									final STEMColor c = colorMap.get(key);
									colorMap.put(selectedPropertyName, c);
									foregroundFillColor = c;
									break;
								}
								// if prefix match
								boolean hit = true;
								for (char c : tail.toCharArray()) {
									if (!Character.isDigit(c)) {
										hit = false;
										break;
									}
								}// all characters in tail
								if(hit){
									// remember the new key in the color map
									final STEMColor c = colorMap.get(key);
									colorMap.put(selectedPropertyName, c);
									foregroundFillColor = c;
									break;
								}
							}
						}
		}

		
		STEMColor retValue = null;
		
		// Update the G2D object with the appropriate intensity of the color
		float alpha = getRelativeValue();
		alpha *= gainFactor;
		// SED 8/4/2009. Make sure alpha is between 0 and 1
		if(alpha > 1.0) alpha = 1.0f;
		if(alpha < 0.0) alpha = 0.0f; // should never happen
		if (alpha < ZERO_RELATIVE_VALUE_THRESHOLD) {
//			gcToUpdate.setAlpha(255);
//			// NOTE: this allows a background color different from the ocean color (JHK)
//			gcToUpdate.setBackground(zero_FillColor);
			//gcToUpdate.setBackground(backgroundFillColor);
			retValue = new STEMColor(zero_FillColor.getRed(), zero_FillColor.getGreen(), zero_FillColor.getBlue(), 0.0f );
		} else {
			if (useLogScaling == true) {
				alpha = performLogScaling(alpha);
			} 
			//TODO Take care of gain factor
//			gcToUpdate.setAlpha((int)(alpha * 255));
//			gcToUpdate.setBackground(foregroundFillColor);
			
			retValue = new STEMColor(foregroundFillColor.getRed(), foregroundFillColor.getGreen(), foregroundFillColor.getBlue(),  alpha);
		}
		
		return retValue;
	}
	
	
	/**
	 * @see org.eclipse.stem.ui.adapters.color.AbstractRelativeValueColorProviderAdapter#updateGC(GC, float, boolean)
	 */
	@Override
	public void updateGC(final GC gcToUpdate,
			final float gainFactor, final boolean useLogScaling) {

		STEMColor color = getColor(gainFactor, useLogScaling);
		
		gcToUpdate.setAlpha((int)(color.getAlpha() * 255));
		gcToUpdate.setBackground(color.toSWTColor(gcToUpdate.getDevice()));
		
		
		
//		final String selectedPropertyName = selectedProperty.getDisplayName(null);
//
//		// Get the color for the selected property (label)
//		if (colorMap.containsKey(selectedPropertyName)) {
//			foregroundFillColor = colorMap.get(selectedPropertyName);
//		} else {
//			// check for complex compartment names and add those to the map if necessary
//			// this way we avoid lots of future string manipulation when we want to find the colors
//			// Check for a prefix match
//						for (String key : colorMap.keySet()) {
//							if((selectedPropertyName.startsWith(key))&&(key.length()>=1)) {
//								// might be right
//								String tail = selectedPropertyName.substring(key.length(), selectedPropertyName.length());
//								//if perfect match (should not happen)
//								if((tail==null)||(tail.length()==0)) {
//									final Color c = colorMap.get(key);
//									colorMap.put(selectedPropertyName, c);
//									foregroundFillColor = c;
//									break;
//								}
//								// if prefix match
//								boolean hit = true;
//								for (char c : tail.toCharArray()) {
//									if (!Character.isDigit(c)) {
//										hit = false;
//										break;
//									}
//								}// all characters in tail
//								if(hit){
//									// remember the new key in the color map
//									final Color c = colorMap.get(key);
//									colorMap.put(selectedPropertyName, c);
//									foregroundFillColor = c;
//									break;
//								}
//							}
//						}
//		}
//
//		// Update the G2D object with the appropriate intensity of the color
//		float alpha = getRelativeValue();
//		alpha *= gainFactor;
//		// SED 8/4/2009. Make sure alpha is between 0 and 1
//		if(alpha > 1.0) alpha = 1.0f;
//		if(alpha < 0.0) alpha = 0.0f; // should never happen
//		if (alpha < ZERO_RELATIVE_VALUE_THRESHOLD) {
//			gcToUpdate.setAlpha(255);
//			// NOTE: this allows a background color different from the ocean color (JHK)
//			gcToUpdate.setBackground(zero_FillColor);
//			//gcToUpdate.setBackground(backgroundFillColor);
//
//		} else {
//			if (useLogScaling == true) {
//				alpha = performLogScaling(alpha);
//			} 
//			//TODO Take care of gain factor
//			gcToUpdate.setAlpha((int)(alpha * 255));
//			gcToUpdate.setBackground(foregroundFillColor);
//		}
	} // setG2DColor

//	/**
//	 * @param alpha
//	 * @return
//	 */
//	private static AlphaComposite makeComposite(final float alpha) {
//		return (AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
//	} // makeComposite

	/**
	 * @param v
	 * @return
	 */
	private float performLogScaling(final float v) {
		double vDouble = v;
		// make sure our linear scale is a fraction between 0.0 and 1.0
		if (vDouble > 1.0) {
			vDouble = 1.0; // saturation
		} else if (v < 0.0) {
			vDouble = 0.0; // should not happen
		}

		// logarithmic color display
		// set scale 1.0 to 100.0
		double vScaled100 = vDouble * 99.0;
		// add 1.0 so we have no zeros
		vScaled100 += 1.0;
		// take the log base 10.0
		double newV = Math.log10(vScaled100);
		// we now have a number between 1 and 2 so divide by 2
		newV /= 2.0;

		return (float) newV;
	} // performLogScaling

	/**
	 * @see org.eclipse.stem.ui.adapters.color.IntensityColorsLabelsMappingColorProviderAdapterFactory.PropertySelectionListener#propertySelected(org.eclipse.emf.edit.provider.ItemPropertyDescriptor)
	 */
	public void propertySelected(ItemPropertyDescriptor selectedProperty) {
		this.selectedProperty = selectedProperty;		
	}

} // IntensityColorsLabelsMappingColorProviderAdapter
