/*
 * Copyright (c) 2011, Patrik Dufresne. All rights reserved.
 * Patrik Dufresne PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.planimod.ui.viewers.planner;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;

import com.patrikdufresne.planner.databinding.ObservableMapPlannerLabelProvider;
import com.patrikdufresne.ui.ColorUtil;

/**
 * This specific implementation provide a different background color for the
 * shift.
 * 
 * @author Patrik Dufresne
 * 
 */
public class ObservableMapPlannerLabelProviderWithColor extends
		ObservableMapPlannerLabelProvider {

	private RGB black = new RGB(0,0,0);
	/**
	 * Map the border color.
	 */
	private Map<RGB, Color> borderColors;

	/**
	 * Map to bind RGB to color.
	 */
	private Map<RGB, Color> colors;

	/**
	 * Create a new label provider with color support.
	 * 
	 * @param attributeMap
	 *            the label map
	 * @param start
	 *            the start date map
	 * @param end
	 *            the end date map
	 * @param color
	 *            the color map.
	 */
	public ObservableMapPlannerLabelProviderWithColor(
			IObservableMap attributeMap, IObservableMap start,
			IObservableMap end, IObservableMap color) {
		super(new IObservableMap[] { attributeMap, start, end, color });
	}

	/**
	 * This implementation dispose the allocated colors.
	 */
	@Override
	public void dispose() {
		try {
			if (this.colors != null) {
				for (Color color : this.colors.values()) {
					color.dispose();
				}
				this.colors = null;
			}
			if (this.borderColors != null) {
				for (Color color : this.borderColors.values()) {
					color.dispose();
				}
				this.borderColors = null;
			}
		} finally {
			super.dispose();
		}
	}

	/**
	 * This implementation return the color for the specified element.
	 */
	@Override
	public Color getBackground(Object element) {
		if (this.attributeMaps[3] != null) {
			Object value = this.attributeMaps[3].get(element);
			if (value instanceof RGB) {
				return getColor((RGB) value);
			}
		}
		return null;
	}

	/**
	 * This implementation generate a border color using the element color.
	 */
	@Override
	public Color getBorderColor(Object element) {
		if (this.attributeMaps[3] != null) {
			Object value = this.attributeMaps[3].get(element);
			if (value instanceof RGB) {
				return getBorderColor((RGB) value);
			}
		}
		return null;
	}
	
	protected Color getBorderColor(RGB value) {
		if (this.borderColors == null) {
			this.borderColors = new HashMap<RGB, Color>();
		}

		// Find the color in the map.
		Color color = this.borderColors.get(value);
		if (color == null) {
			// Blend the color
			value = ColorUtil.blend(value, this.black, 50);
			color = new Color(Display.getDefault(), value);
			this.borderColors.put(value, color);
		}
		return color;
	}
	
	/**
	 * This function is used to get a color object from the RGB. If the color is
	 * already register in the map, this value is return.
	 * 
	 * @param value
	 *            the RGB value
	 * @return the color
	 */
	protected Color getColor(RGB value) {
		if (this.colors == null) {
			this.colors = new HashMap<RGB, Color>();
		}

		// Find the color in the map.
		Color color = this.colors.get(value);
		if (color == null) {
			color = new Color(Display.getDefault(), value);
			this.colors.put(value, color);
		}
		return color;
	}

}
