/*
 * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  o Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  o Neither the name of Substance Kirill Grouchnikov nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.jvnet.substance.utils;

import java.awt.Component;
import java.util.Set;

import org.jvnet.lafwidget.animation.*;

/**
 * Fade-related utilities.
 * 
 * @author Kirill Grouchnikov.
 */
public class SubstanceFadeUtilities {
	/**
	 * Returns the component that is being tracked by the {@link FadeTracker}
	 * with the highest value of the fade cycle.
	 * 
	 * @param fadeKind
	 *            Fade kind.
	 * @param comps
	 *            Components.
	 * @return The component that is being tracked by the {@link FadeTracker}
	 *         with the highest value of the fade cycle. May be
	 *         <code>null</code>.
	 */
	public static Component getTracked(FadeKind fadeKind, Component... comps) {
		FadeTracker tracker = FadeTracker.getInstance();
		Component result = null;
		float highest = -1.0f;
		for (Component comp : comps) {
			if (tracker.isTracked(comp, fadeKind)) {
				float fade = tracker.getFade(comp, fadeKind);
				if (fade > highest) {
					result = comp;
					highest = fade;
				}
			}
		}
		return result;
	}

	/**
	 * Returns the highest fade cycle for the specified component and the fade
	 * kind.
	 * 
	 * @param fadeKind
	 *            Fade kind.
	 * @param comps
	 *            Components.
	 * @return The highest fade cycle for the specified component and the fade
	 *         kind.
	 */
	public static FadeState getFadeStateWithHighestFadeCycle(FadeKind fadeKind,
			Component... comps) {
		FadeTracker tracker = FadeTracker.getInstance();
		FadeState result = null;
		float highest = -1.0f;
		for (Component comp : comps) {
			FadeState curr = tracker.getFadeState(comp, fadeKind);
			if (curr != null) {
				if (curr.getFadePosition() > highest) {
					result = curr;
					highest = curr.getFadePosition();
				}
			}
		}
		return result;
	}

	/**
	 * Returns the first matching fade state for the specified component.
	 * 
	 * @param comp
	 *            Component.
	 * @param fadeKinds
	 *            A list of fade kinds. The list is scanned from the start. The
	 *            first fade kind that is currently "happening" on the specified
	 *            component will be used to fetch the fade state.
	 * @return The first matching fade state for the specified component.
	 */
	public static FadeState getFadeState(Component comp, FadeKind... fadeKinds) {
		FadeTracker tracker = FadeTracker.getInstance();
		for (FadeKind fadeKind : fadeKinds) {
			FadeState result = tracker.getFadeState(comp, fadeKind);
			if (result != null)
				return result;
		}
		return null;
	}

	/**
	 * Returns the first matching fade state for the specified component.
	 * 
	 * @param comp
	 *            Component.
	 * @param comparable
	 *            Identifier of a sub-entity.
	 * @param fadeKinds
	 *            A list of fade kinds. The list is scanned from the start. The
	 *            first fade kind that is currently "happening" on the specified
	 *            component will be used to fetch the fade state.
	 * @return The first matching fade state for the specified component.
	 */
	public static FadeState getFadeState(Component comp,
			Comparable<?> comparable, FadeKind... fadeKinds) {
		FadeTracker tracker = FadeTracker.getInstance();
		for (FadeKind fadeKind : fadeKinds) {
			FadeState result = tracker.getFadeState(comp, comparable, fadeKind);
			if (result != null)
				return result;
		}
		return null;
	}

	/**
	 * Returns the first matching fade state for the specified component.
	 * 
	 * @param comp
	 *            Component.
	 * @param comparables
	 *            Identifiers of sub-entities.
	 * @param fadeKinds
	 *            Fade kinds. The list is scanned from the start. The first fade
	 *            kind that is currently "happening" on the specified component
	 *            will be used to fetch the fade state.
	 * @return The first matching fade state for the specified component.
	 */
	public static FadeState getFadeState(Component comp,
			Comparable<?>[] comparables, FadeKind[] fadeKinds) {
		FadeTracker tracker = FadeTracker.getInstance();
		for (FadeKind fadeKind : fadeKinds) {
			for (Comparable<?> comparable : comparables) {
				FadeState result = tracker.getFadeState(comp, comparable,
						fadeKind);
				if (result != null)
					return result;
			}
		}
		return null;
	}

	/**
	 * Cancels the specified fade sequences.
	 * 
	 * @param initiatedFadeSequences
	 *            Fade sequence IDs to cancel.
	 */
	public static void cancelFades(Set<Long> initiatedFadeSequences) {
		FadeTracker fadeTrackerInstance = FadeTracker.getInstance();
		for (long fadeId : initiatedFadeSequences) {
			fadeTrackerInstance.cancelFadeInstance(fadeId);
		}
	}
}
