package aurelienribon.tweenengine;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * A TweenManager updates all your tweens and timelines at once.
 * Its main interest is that it handles the tween/timeline life-cycles for you,
 * as well as the pooling constraints (if object pooling is enabled).
 * <p/>
 *
 * Just give it a bunch of tweens or timelines and call update() periodically,
 * you don't need to care for anything else! Relax and enjoy your animations.
 *
 * @see Tween
 * @see Timeline
 * @author Aurelien Ribon | http://www.aurelienribon.com/
 */
public class TweenManager {
	// -------------------------------------------------------------------------
	// Static API
	// -------------------------------------------------------------------------

	/**
	 * Disables or enables the "auto remove" mode of any tween manager for a
	 * particular tween or timeline. This mode is activated by default. The
	 * interest of desactivating it is to prevent some tweens or timelines from
	 * being automatically removed from a manager once they are finished.
	 * Therefore, if you update a manager backwards, the tweens or timelines
	 * will be played again, even if they were finished.
	 */
	public static void setAutoRemove(BaseTween<?> object, boolean value) {
		object.isAutoRemoveEnabled = value;
	}

	/**
	 * Disables or enables the "auto start" mode of any tween manager for a
	 * particular tween or timeline. This mode is activated by default. If it
	 * is not enabled, add a tween or timeline to any manager won't start it
	 * automatically, and you'll need to call .start() manually on your object.
	 */
	public static void setAutoStart(BaseTween<?> object, boolean value) {
		object.isAutoStartEnabled = value;
	}

	// -------------------------------------------------------------------------
	// Public API
	// -------------------------------------------------------------------------

	private final ArrayList<BaseTween<?>> objects = new ArrayList<BaseTween<?>>(20);
	private boolean isPaused = false;

	/**
	 * Adds a tween or timeline to the manager and starts or restarts it.
	 *
	 * @return The manager, for instruction chaining.
	 */
	public TweenManager add(BaseTween<?> object) {
		if (!objects.contains(object)) objects.add(object);
		if (object.isAutoStartEnabled) object.start();
		return this;
	}

	/**
	 * Returns true if the manager contains any valid interpolation associated
	 * to the given target object.
	 */
	public boolean containsTarget(Object target) {
		for (int i=0, n=objects.size(); i<n; i++) {
			BaseTween<?> obj = objects.get(i);
			if (obj.containsTarget(target)) return true;
		}
		return false;
	}

	/**
	 * Returns true if the manager contains any valid interpolation associated
	 * to the given target object and to the given tween type.
	 */
	public boolean containsTarget(Object target, int tweenType) {
		for (int i=0, n=objects.size(); i<n; i++) {
			BaseTween<?> obj = objects.get(i);
			if (obj.containsTarget(target, tweenType)) return true;
		}
		return false;
	}

	/**
	 * Kills every managed tweens and timelines.
	 */
	public void killAll() {
		for (int i=0, n=objects.size(); i<n; i++) {
			BaseTween<?> obj = objects.get(i);
			obj.kill();
		}
	}

	/**
	 * Kills every tweens associated to the given target. Will also kill every
	 * timelines containing a tween associated to the given target.
	 */
	public void killTarget(Object target) {
		for (int i=0, n=objects.size(); i<n; i++) {
			BaseTween<?> obj = objects.get(i);
			obj.killTarget(target);
		}
	}

	/**
	 * Kills every tweens associated to the given target and tween type. Will
	 * also kill every timelines containing a tween associated to the given
	 * target and tween type.
	 */
	public void killTarget(Object target, int tweenType) {
		for (int i=0, n=objects.size(); i<n; i++) {
			BaseTween<?> obj = objects.get(i);
			obj.killTarget(target, tweenType);
		}
	}

	/**
	 * Increases the minimum capacity of the manager. Defaults to 20.
	 */
	public void ensureCapacity(int minCapacity) {
		objects.ensureCapacity(minCapacity);
	}

	/**
	 * Pauses the manager. Further update calls won't have any effect.
	 */
	public void pause() {
		isPaused = true;
	}

	/**
	 * Resumes the manager, if paused.
	 */
	public void resume() {
		isPaused = false;
	}

	/**
	 * Updates every tweens with a delta time ang handles the tween life-cycles
	 * automatically. If a tween is finished, it will be removed from the
	 * manager. The delta time represents the elapsed time between now and the
	 * last update call. Each tween or timeline manages its local time, and adds
	 * this delta to its local time to update itself.
	 * <p/>
	 *
	 * Slow motion, fast motion and backward play can be easily achieved by
	 * tweaking this delta time. Multiply it by -1 to play the animation
	 * backward, or by 0.5 to play it twice slower than its normal speed.
	 */
	public void update(float delta) {
		for (int i=objects.size()-1; i>=0; i--) {
			BaseTween<?> obj = objects.get(i);
			if (obj.isFinished() && obj.isAutoRemoveEnabled) {
				objects.remove(i);
				obj.free();
			}
		}

		if (!isPaused) {
			if (delta >= 0) {
				for (int i=0, n=objects.size(); i<n; i++) objects.get(i).update(delta);
			} else {
				for (int i=objects.size()-1; i>=0; i--) objects.get(i).update(delta);
			}
		}
	}

	/**
	 * Gets the number of managed objects. An object may be a tween or a
	 * timeline. Note that a timeline only counts for 1 object, since it
	 * manages its children itself.
	 * <p/>
	 * To get the count of running tweens, see {@link #getRunningTweensCount()}.
	 */
	public int size() {
		return objects.size();
	}

	/**
	 * Gets the number of running tweens. This number includes the tweens
	 * located inside timelines (and nested timelines).
	 * <p/>
	 * <b>Provided for debug purpose only.</b>
	 */
	public int getRunningTweensCount() {
		return getTweensCount(objects);
	}

	/**
	 * Gets the number of running timelines. This number includes the timelines
	 * nested inside other timelines.
	 * <p/>
	 * <b>Provided for debug purpose only.</b>
	 */
	public int getRunningTimelinesCount() {
		return getTimelinesCount(objects);
	}

	/**
	 * Gets an immutable list of every managed object.
	 * <p/>
	 * <b>Provided for debug purpose only.</b>
	 */
	public List<BaseTween<?>> getObjects() {
		return Collections.unmodifiableList(objects);
	}

	// -------------------------------------------------------------------------
	// Helpers
	// -------------------------------------------------------------------------

	private static int getTweensCount(List<BaseTween<?>> objs) {
		int cnt = 0;
		for (int i=0, n=objs.size(); i<n; i++) {
			BaseTween<?> obj = objs.get(i);
			if (obj instanceof Tween) cnt += 1;
			else cnt += getTweensCount(((Timeline)obj).getChildren());
		}
		return cnt;
	}

	private static int getTimelinesCount(List<BaseTween<?>> objs) {
		int cnt = 0;
		for (int i=0, n=objs.size(); i<n; i++) {
			BaseTween<?> obj = objs.get(i);
			if (obj instanceof Timeline) {
				cnt += 1 + getTimelinesCount(((Timeline)obj).getChildren());
			}
		}
		return cnt;
	}
}
