package aurelienribon.tweenengine;

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

/**
 * A Timeline can be used to create complex animations made of sequences and
 * parallel sets of Tweens.
 * <p/>
 *
 * The following example will create an animation sequence composed of 5 parts:
 * <p/>
 *
 * 1. First, opacity and scale are set to 0 (with Tween.set() calls).<br/>
 * 2. Then, opacity and scale are animated in parallel.<br/>
 * 3. Then, the animation is paused for 1s.<br/>
 * 4. Then, position is animated to x=100.<br/>
 * 5. Then, rotation is animated to 360°.
 * <p/>
 *
 * This animation will be repeated 5 times, with a 500ms delay between each
 * iteration:
 * <br/><br/>
 *
 * <pre> {@code
 * Timeline.createSequence()
 *     .push(Tween.set(myObject, OPACITY).target(0))
 *     .push(Tween.set(myObject, SCALE).target(0, 0))
 *     .beginParallel()
 *          .push(Tween.to(myObject, OPACITY, 0.5f).target(1).ease(Quad.INOUT))
 *          .push(Tween.to(myObject, SCALE, 0.5f).target(1, 1).ease(Quad.INOUT))
 *     .end()
 *     .pushPause(1.0f)
 *     .push(Tween.to(myObject, POSITION_X, 0.5f).target(100).ease(Quad.INOUT))
 *     .push(Tween.to(myObject, ROTATION, 0.5f).target(360).ease(Quad.INOUT))
 *     .repeat(5, 0.5f)
 *     .start(myManager);
 * }</pre>
 *
 * @see Tween
 * @see TweenManager
 * @see TweenCallback
 * @author Aurelien Ribon | http://www.aurelienribon.com/
 */
public final class Timeline extends BaseTween<Timeline> {
	// -------------------------------------------------------------------------
	// Static -- pool
	// -------------------------------------------------------------------------

	private static final Pool.Callback<Timeline> poolCallback = new Pool.Callback<Timeline>() {
		@Override public void onPool(Timeline obj) {obj.reset();}
		@Override public void onUnPool(Timeline obj) {obj.reset();}
	};

	static final Pool<Timeline> pool = new Pool<Timeline>(10, poolCallback) {
		@Override protected Timeline create() {return new Timeline();}
	};

	/**
	 * Used for debug purpose. Gets the current number of empty timelines that
	 * are waiting in the Timeline pool.
	 */
	public static int getPoolSize() {
		return pool.size();
	}

	/**
	 * Increases the minimum capacity of the pool. Capacity defaults to 10.
	 */
	public static void ensurePoolCapacity(int minCapacity) {
		pool.ensureCapacity(minCapacity);
	}

	// -------------------------------------------------------------------------
	// Static -- factories
	// -------------------------------------------------------------------------

	/**
	 * Creates a new timeline with a 'sequence' behavior. Its children will
	 * be delayed so that they are triggered one after the other.
	 */
	public static Timeline createSequence() {
		Timeline tl = pool.get();
		tl.setup(Modes.SEQUENCE);
		return tl;
	}

	/**
	 * Creates a new timeline with a 'parallel' behavior. Its children will be
	 * triggered all at once.
	 */
	public static Timeline createParallel() {
		Timeline tl = pool.get();
		tl.setup(Modes.PARALLEL);
		return tl;
	}

	// -------------------------------------------------------------------------
	// Attributes
	// -------------------------------------------------------------------------

	private enum Modes {SEQUENCE, PARALLEL}

	private final List<BaseTween<?>> children = new ArrayList<BaseTween<?>>(10);
	private Timeline current;
	private Timeline parent;
	private Modes mode;
	private boolean isBuilt;

	// -------------------------------------------------------------------------
	// Setup
	// -------------------------------------------------------------------------

	private Timeline() {
		reset();
	}

	@Override
	protected void reset() {
		super.reset();

		children.clear();
		current = parent = null;

		isBuilt = false;
	}

	private void setup(Modes mode) {
		this.mode = mode;
		this.current = this;
	}

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

	/**
	 * Adds a Tween to the current timeline.
	 *
	 * @return The current timeline, for chaining instructions.
	 */
	public Timeline push(Tween tween) {
		if (isBuilt) throw new RuntimeException("You can't push anything to a timeline once it is started");
		current.children.add(tween);
		return this;
	}

	/**
	 * Nests a Timeline in the current one.
	 *
	 * @return The current timeline, for chaining instructions.
	 */
	public Timeline push(Timeline timeline) {
		if (isBuilt) throw new RuntimeException("You can't push anything to a timeline once it is started");
		if (timeline.current != timeline) throw new RuntimeException("You forgot to call a few 'end()' statements in your pushed timeline");
		timeline.parent = current;
		current.children.add(timeline);
		return this;
	}

	/**
	 * Adds a pause to the timeline. The pause may be negative if you want to
	 * overlap the preceding and following children.
	 *
	 * @param time A positive or negative duration.
	 * @return The current timeline, for chaining instructions.
	 */
	public Timeline pushPause(float time) {
		if (isBuilt) throw new RuntimeException("You can't push anything to a timeline once it is started");
		current.children.add(Tween.mark().delay(time));
		return this;
	}

	/**
	 * Starts a nested timeline with a 'sequence' behavior. Don't forget to
	 * call {@link end()} to close this nested timeline.
	 *
	 * @return The current timeline, for chaining instructions.
	 */
	public Timeline beginSequence() {
		if (isBuilt) throw new RuntimeException("You can't push anything to a timeline once it is started");
		Timeline tl = pool.get();
		tl.parent = current;
		tl.mode = Modes.SEQUENCE;
		current.children.add(tl);
		current = tl;
		return this;
	}

	/**
	 * Starts a nested timeline with a 'parallel' behavior. Don't forget to
	 * call {@link end()} to close this nested timeline.
	 *
	 * @return The current timeline, for chaining instructions.
	 */
	public Timeline beginParallel() {
		if (isBuilt) throw new RuntimeException("You can't push anything to a timeline once it is started");
		Timeline tl = pool.get();
		tl.parent = current;
		tl.mode = Modes.PARALLEL;
		current.children.add(tl);
		current = tl;
		return this;
	}

	/**
	 * Closes the last nested timeline.
	 *
	 * @return The current timeline, for chaining instructions.
	 */
	public Timeline end() {
		if (isBuilt) throw new RuntimeException("You can't push anything to a timeline once it is started");
		if (current == this) throw new RuntimeException("Nothing to end...");
		current = current.parent;
		return this;
	}

	/**
	 * Gets a list of the timeline children. If the timeline is started, the
	 * list will be immutable.
	 */
	public List<BaseTween<?>> getChildren() {
		if (isBuilt) return Collections.unmodifiableList(current.children);
		else return current.children;
	}

	// -------------------------------------------------------------------------
	// Overrides
	// -------------------------------------------------------------------------

	@Override
	public Timeline build() {
		if (isBuilt) return this;

		duration = 0;

		for (int i=0; i<children.size(); i++) {
			BaseTween<?> obj = children.get(i);

			if (obj.getRepeatCount() < 0) throw new RuntimeException("You can't push an object with infinite repetitions in a timeline");
			obj.build();

			switch (mode) {
				case SEQUENCE:
					float tDelay = duration;
					duration += obj.getFullDuration();
					obj.delay += tDelay;
					break;

				case PARALLEL:
					duration = Math.max(duration, obj.getFullDuration());
					break;
			}
		}

		isBuilt = true;
		return this;
	}

	@Override
	public Timeline start() {
		super.start();

		for (int i=0; i<children.size(); i++) {
			BaseTween<?> obj = children.get(i);
			obj.start();
		}

		return this;
	}

	@Override
	public void free() {
		for (int i=children.size()-1; i>=0; i--) {
			BaseTween<?> obj = children.remove(i);
			obj.free();
		}

		pool.free(this);
	}

	@Override
	protected void updateOverride(int step, int lastStep, boolean isIterationStep, float delta) {
		if (!isIterationStep && step > lastStep) {
			assert delta >= 0;
			float dt = isReverse(lastStep) ? -delta-1 : delta+1;
			for (int i=0, n=children.size(); i<n; i++) children.get(i).update(dt);
			return;
		}

		if (!isIterationStep && step < lastStep) {
			assert delta <= 0;
			float dt = isReverse(lastStep) ? -delta-1 : delta+1;
			for (int i=children.size()-1; i>=0; i--) children.get(i).update(dt);
			return;
		}

		assert isIterationStep;

		if (step > lastStep) {
			if (isReverse(step)) {
				forceEndValues();
				for (int i=0, n=children.size(); i<n; i++) children.get(i).update(delta);
			} else {
				forceStartValues();
				for (int i=0, n=children.size(); i<n; i++) children.get(i).update(delta);
			}

		} else if (step < lastStep) {
			if (isReverse(step)) {
				forceStartValues();
				for (int i=children.size()-1; i>=0; i--) children.get(i).update(delta);
			} else {
				forceEndValues();
				for (int i=children.size()-1; i>=0; i--) children.get(i).update(delta);
			}

		} else {
			float dt = isReverse(step) ? -delta : delta;
			if (delta >= 0) for (int i=0, n=children.size(); i<n; i++) children.get(i).update(dt);
			else for (int i=children.size()-1; i>=0; i--) children.get(i).update(dt);
		}
	}

	// -------------------------------------------------------------------------
	// BaseTween impl.
	// -------------------------------------------------------------------------

	@Override
	protected void forceStartValues() {
		for (int i=children.size()-1; i>=0; i--) {
			BaseTween<?> obj = children.get(i);
			obj.forceToStart();
		}
	}

	@Override
	protected void forceEndValues() {
		for (int i=0, n=children.size(); i<n; i++) {
			BaseTween<?> obj = children.get(i);
			obj.forceToEnd(duration);
		}
	}

	@Override
	protected boolean containsTarget(Object target) {
		for (int i=0, n=children.size(); i<n; i++) {
			BaseTween<?> obj = children.get(i);
			if (obj.containsTarget(target)) return true;
		}
		return false;
	}

	@Override
	protected boolean containsTarget(Object target, int tweenType) {
		for (int i=0, n=children.size(); i<n; i++) {
			BaseTween<?> obj = children.get(i);
			if (obj.containsTarget(target, tweenType)) return true;
		}
		return false;
	}
}
