/*
 * @(#)DeleteBSTAnimation.java
 *
 * Last Modified: 9/15/01
 */

 import java.util.*;
 import java.awt.*;
 import java.awt.geom.*;

/** *
 	* The Animation object that defines the Deletion of a node in a BSTTree. Two constructors exist,
 	* one setting the animator and line paints(preferred), the other using defaults. The animation builds RotationBSTAnimations
 	* as it goes, keeping only one currently animating rotation and allowing rewinding only to the previous
 	* rotation. <p>
	*
	* @author  Corey Sanders
	* @version 1.3 9/15/01
 	*/
public class DeleteBSTAnimation extends AbstractAnimation implements AnimationListener {


	/**
	 * Constant that defines the starting location.
	 */
	protected final int START = 0;

	/**
	 * Constant that defines the fading of the erasing node.
	 */
	protected final int FADE_NODE = 1;

	/**
	 * Defines the partitioning through the tree.
	 */
	protected int PARTITION_TREE = 2;

	/**
	 * Defines the final move through the tree.
	 */
	protected int FINAL_MOVE = 3;

	/**
	 * Defines the final move through the tree.
	 */
	protected int END = 4;

	/**
	 * Refers to the current PartitionBSTAnimation being drawn.
	 */
	 protected PartitionBSTAnimation currentPartition;

	/**
	 * Refers to the final moving nodes.
	 */
	protected MovingBSTTreeAnimation finalMovingNodes;

	/**
	 * Private doubles used to hold the current and previous location steps.
	 */
	protected double currentLocation = 0.0;
	protected double previousLocation = 0.0;


	/**
	 * PaintSettings for the left line drawn during partitioning.
	 */
	PaintSettings leftLinePaintSettings = null;

	/**
	 * PaintSettings for the right line drawn during partitioning.
	 */
	PaintSettings rightLinePaintSettings = null;

	/**
	 * Holds the node that is erasing.
	 */
	private BSTTree erasingNode;

	/**
	 * Holds the node that is replacing.
	 */
	private BSTTree replacingNode;


	/**
	 * The constructor which initiates the status and prepares the line paints. The node
	 * which is being deleted must be passed.
	 *
	 * @param erasingNode the BSTTree which is being deleted.
	 * @param RightLinePaintSettings the paint for the right line when drawing the deletion.
	 * @param LeftLinePaintSettings the paint for the left line when drawing the deletion
	 * @param startingCmd the Animation command that this should start.
	 * @param stepTime the time for each step of the Animation. Sets the initial value.
	 */
	public DeleteBSTAnimation(BSTTree erasingNode, PaintSettings RightLinePaintSettings, PaintSettings LeftLinePaintSettings, String startingCmd, int stepTime) {

		// Call to AbstractAnimation
		super();

		// If null colors, set defaults
		if (RightLinePaintSettings == null) {
			RightLinePaintSettings = PaintSettings.getScheme(PaintSettings.RED);
		}
		if (LeftLinePaintSettings == null) {
			LeftLinePaintSettings = PaintSettings.getScheme(PaintSettings.BLUE);
		}
		// Set line colors
		setLeftLinePaintSettings(LeftLinePaintSettings);
		setRightLinePaintSettings(RightLinePaintSettings);

		// Set erasing node
		setErasingNode(erasingNode);

		setStartingCommand(startingCmd);
		setStepTime(stepTime);

	}



	/**
	 * The constructor which initiates the status and sets the line paints to null.
	 *
	 * @param erasingNode the BSTTree which is deleted during the deletion.
	 */
	public DeleteBSTAnimation(BSTTree erasingNode) {
		this(erasingNode, null, null, Animation.PLAY, DEFAULT_STEP);
	}

	/************************/
	/* Accessor methods     */
	/************************/

	/**
	 * Gets the node being deleted during the deletion.
	 *
	 * @return BSTTree of the node being deleted.
	 */
	public BSTTree getErasingNode() {
		return erasingNode;
	}

	/**
	 * Gets the node being replaced during the deletion.
	 *
	 * @return BSTTree of the node being replaced.
	 */
	public BSTTree getReplacingNode() {
		return replacingNode;
	}

	/**
	 * Gets the PaintSettings for the right line of the partition for deletion.
 	 *
     * @return PaintSettings for the right line of the deletion.
     */
	public PaintSettings getRightLinePaintSettings() {
		return rightLinePaintSettings;
	}

	/**
	 * Gets the paint for the left line of the partition for deletion.
 	 *
     * @return Paint for the left line of the deletion.
     */
	public PaintSettings getLeftLinePaintSettings() {
		return leftLinePaintSettings;
	}

	/************************/
	/* Mutator methods     */
	/************************/

	/**
	 * Sets the node being deleted during the Deletion.
	 *
	 * @param BSTTree of the node being deleted.
	 */
	public void setErasingNode(BSTTree node) {
		erasingNode = node;
	}

	/**
	 * Sets the node being replaced during the Deletion.
	 *
	 * @param BSTTree of the node being replaced.
	 */
	public void setReplacingNode(BSTTree node) {
		replacingNode = node;
	}

	/**
	 * Sets the PaintSettings for the right line of the partition for deletion.
 	 *
     * @param rightPaintSettings for the right line of the deletion.
     */
	public void setRightLinePaintSettings(PaintSettings rightPaintSettings) {
		rightLinePaintSettings=rightPaintSettings;
	}

	/**
	 * Sets the paint for the left line of the partition for deletion.
 	 *
     * @return leftPaint for the left line of the deletion.
     */
	public void setLeftLinePaintSettings(PaintSettings leftPaintSettings) {
		leftLinePaintSettings=leftPaintSettings;
	}

	/***********************/
	/* Creation Methods    */
	/***********************/

	/**
	 * Creates the moving nodes corresponding to the descendant of the rotation.
	 */
	protected void createFinalMovingNodes() {
		// Intialize
		finalMovingNodes = new MovingBSTTreeAnimation();

		// Head node
		BSTTree headNode = (BSTTree)getErasingNode().getHead().getChild();

		// Head moving node.
		MovingBSTTree headMovingNode = new MovingBSTTree(headNode);

		if (headNode != getErasingNode() && headNode.isAnimateDrawing() ) {
			// If there is a grandchild.
			headMovingNode = new MovingBSTTree(headNode);

			// Add grandchild to descendant animation
			finalMovingNodes.add(headMovingNode, headNode);

			headMovingNode.setMovePosition(MovingBSTTree.FOLLOW_NODE);

			// Set listeners
			finalMovingNodes.addAnimationListener(headNode);
			(headNode).addAnimator(finalMovingNodes);
		}
		// Add all children
		addNode((BSTTree)headNode.getLeftTree(), finalMovingNodes, MovingBSTTree.FOLLOW_NODE, headMovingNode);
		addNode((BSTTree)headNode.getRightTree(), finalMovingNodes, MovingBSTTree.FOLLOW_NODE, headMovingNode);

	}

	/**
	 * Adds all children nodes to the animator list, setting the Moving node as its parent. The move position
	 * defines the moving of the new node.
	 *
	 * @param node the node which the MovingBSTTree made imitates.
	 * @param animator the MovingBSTTreeAnimation to which the new MovingBSTTree node is added.
	 * @param movePostion the moving position of the new MovingBSTTree.
	 * @param parent <code>MovingBSTTree</code> parent for the node, specifically for following the node.
	 */
	protected void addNode(BSTTree node, MovingBSTTreeAnimation animator, int movePosition, MovingBSTTree parent) {
		if (node.isEmpty())
			return;

		// Create new MovingBSTTree
		MovingBSTTree movingNode = new MovingBSTTree(node, parent);

		if (node != getErasingNode() && node.isAnimateDrawing()) {


			// Sets the move position
			movingNode.setMovePosition(movePosition);

			// Adds the animator to the MovingBSTTreeAnimation
			animator.add(movingNode, node);

			// Adds the listener to the animation and the animation to the node.
			animator.addAnimationListener(node);
			node.addAnimator(animator);
		}

		// Recursively goes through children
		addNode((BSTTree)node.getLeftTree(), animator, MovingBSTTree.FOLLOW_NODE, movingNode);
		addNode((BSTTree)node.getRightTree(), animator, MovingBSTTree.FOLLOW_NODE, movingNode);


	}

	/*********************/
	/* Animation methods */
	/*********************/


	/**
	 * Draws the animation of the next step, using the status of the animation (Animation.PLAY, Animation.PAUSE and so forth).
	 * After completing the drawing, the Animation sends an AnimationEvent to all its listeners, indicating
	 * any information that the listerners may wish to use.
	 * <b> BSTTreeHead calls: </b>
	 * <ul>
	 * <li><code>removeTreeType</code> - to do the final deletion in the actual code (after partitioning has occured)</li>
	 * </ul>
	 * <b> Other Animation Objects used: </b>
	 * <ul>
	 * <li>PartitionBSTAnimation</li>
	 * <li>MovingBSTTreeAnimation</li>
	 * </ul>
	 *
	 *
	 * @param g2 the graphics to which the animation step should be drawn.
	 * @param startingStatus the status used as the starting command of animation, if needed.
	 */
	public void drawAnimation(Graphics2D g2, String startingStatus) {
		setStartingCommand(startingStatus);

		// Starting Finish status (set prior to call)
		if (getStatus().equals(Animation.FINISH)) {
			// In partitioning
			if (currentLocation == PARTITION_TREE) {

				// FINISH partition
				currentPartition.setStatus(Animation.FINISH);
				currentPartition.drawAnimation(g2, Animation.FINISH);
			}
			if (currentLocation > PARTITION_TREE) {
				// FINISH final moving
				finalMovingNodes.setStatus(Animation.FINISH);
				finalMovingNodes.drawAnimation(g2, Animation.FINISH);
			}

			// Do actual deletion in tree (Setting the correct final location).
			getErasingNode().getHead().removeTreeType(getErasingNode());
		}


		// BEGIN status
		if (getStatus().equals(Animation.BEGIN)) {
			// Init
			currentLocation = 0;
			previousLocation = 0;

			// Set listeners
			getErasingNode().addAnimator(this);
			this.addAnimationListener(getErasingNode());

			// Redraw
			messageAction(Animation.REDRAW);

			animationAction();

			// Original message
			messageAction(Animation.BEGIN + " Deletion of "+getErasingNode().getKey().toString());

			// set starting status
			setStatus(getStartingCommand());

			// Draw to animating graphic
			getErasingNode().drawNodeAndLink(g2);

			return;

		}

		if (!getStatus().equals(Animation.FINISH)) {
			// DRAW Dotted Line
			drawDottedLine(g2, currentLocation);
		}


		// Currently on a step and no changes have occured. Return to startingStatus
		if (getStatus().equals(Animation.STEP)) {
			setStatus(getStartingCommand());
		}


		// PLAY status
		if (getStatus().equals(Animation.PLAY)) {

			messageAction(Animation.PLAY);

			// Only Increment if fading or final move
			if (currentLocation <= FADE_NODE || currentLocation >= FINAL_MOVE) {
				previousLocation = currentLocation;

				if(getStep()) { // Skip middle animation steps.
					currentLocation = Math.ceil(currentLocation) + getStepSize();
				}
				else { // Normal step
					currentLocation += getStepSize();
				}
			}


			// The fading out of the node.
			if (currentLocation < FADE_NODE) {

				// Set alpha for fade
				float currentAlpha = (float)((double)FADE_NODE - currentLocation);

				// Erasing node with alpha
				getErasingNode().getSettings().setNodeComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				getErasingNode().getSettings().setLeftLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				getErasingNode().getSettings().setRightLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				((DrawableKey)getErasingNode().getValue()).getSettings().setKeyComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));

				// Draw to animating graphic
				getErasingNode().drawNodeAndLink(g2);

			}
			// Finish with fading
			else if ((currentLocation >= FADE_NODE) && (previousLocation <= FADE_NODE)) {

				previousLocation = currentLocation;
				// Step
				setStatus(Animation.STEP);

				// Empty right tree
				if (getErasingNode().getRightTree().isEmpty()) {
					// Empty Left tree
					if (getErasingNode().getLeftTree().isEmpty()) {
						// Do actual deletion in tree (Setting the correct final location).
						// Tree finishes cleared.
						getErasingNode().getHead().removeTreeType(getErasingNode());
						if (getErasingNode().getHead().isTreeEmpty()) {
							messageAction("Resulting Tree is Empty");
						}
						setReplacingNode(null);
						setStatus(Animation.FINISH);
					}
					// Non-Empty Left Tree
					else {
						// Create final moving nodes starting at previous location.
						createFinalMovingNodes();

						// Set replacing node as left tree
						setReplacingNode((BSTTree)getErasingNode().getLeftTree());

						// Do actual deletion in tree (Setting the correct final location).
						getErasingNode().getHead().removeTreeType(getErasingNode());

						currentLocation = FINAL_MOVE;

						messageAction("No right Tree : Replace with Left tree");

						// REDRAW Message
						messageAction(Animation.REDRAW);
						// Set begin of finalMovingNodes
						finalMovingNodes.drawAnimation(g2, Animation.PLAY);
					}

				}
				// Non-Empty Right Tree
				else {
					// Partition element
					currentLocation = PARTITION_TREE;

					messageAction("Partition the smallest node of right subtree");

					currentPartition = (PartitionBSTAnimation)((BSTTreeHead)getErasingNode().getHead()).makePartitionAnimation((BSTTree)getErasingNode().getRightTree(), 0);

					currentPartition.addAnimationListener(this);

					currentPartition.drawAnimation(g2, Animation.PLAY);

					// Do not allow the erased node draw during the Partition
					getErasingNode().setAnimateDrawing(false);
				}
			}

			// The partition of the tree
			else if (currentLocation == PARTITION_TREE) {
				// Set values for animation
				currentPartition.setStepTime(getStepTime());
				currentPartition.setStep(getStep());

				// Set play status
				currentPartition.setStatus(Animation.PLAY);

				// Draw rotation animation
				currentPartition.drawAnimation(g2, Animation.PLAY);

				if (currentPartition.getStatus().equals(Animation.FINISH)) {
					setReplacingNode((BSTTree)getErasingNode().getRightTree());

				 	// Step
					setStatus(Animation.STEP);

					// Create final moving nodes starting at previous location.
					createFinalMovingNodes();


					// Do actual deletion in tree (Setting the correct final location).
					getErasingNode().getHead().removeTreeType(getErasingNode());


					// REDRAW Message
					messageAction(Animation.REDRAW);
					// Beginning final moving Nodes
					finalMovingNodes.drawAnimation(g2, Animation.PLAY);

					messageAction("Replace erased node with partitioned node " + getReplacingNode().getKey().toString());

					currentLocation = FINAL_MOVE;

				}
			}

			// The final move of the node
			else if (currentLocation < END) {
				// Set play status
				finalMovingNodes.setStatus(Animation.PLAY);

				// Set values for animation
				finalMovingNodes.setStepTime(getStepTime());
				finalMovingNodes.setStep(getStep());

				// Draw animation
				finalMovingNodes.drawAnimation(g2, Animation.PLAY);

			}

			// Completely finished
			if (currentLocation >= END) {

				// Set values for animation
				finalMovingNodes.setStepTime(getStepTime());
				finalMovingNodes.setStep(getStep());

				// Set play status
				finalMovingNodes.setStatus(Animation.PLAY);
				// Draw animation
				finalMovingNodes.drawAnimation(g2, Animation.PLAY);
				// Set status of moving animation
				finalMovingNodes.setStatus(Animation.FINISH);
				// Draw animation
				finalMovingNodes.drawAnimation(g2, Animation.FINISH);
				// Set own status
				setStatus(Animation.FINISH);
			}

		}

		// REWIND status
		if (getStatus().equals(Animation.REWIND)) {

			messageAction(Animation.REWIND);

			if (currentLocation <= FADE_NODE || currentLocation >= FINAL_MOVE) {

				previousLocation = currentLocation;

				if(getStep()) { // Skip middle Animation Steps
					currentLocation = Math.floor(currentLocation) - getStepSize();
				}
				else { // Normal Step
					currentLocation -= getStepSize();
				}
			}

			// Rewind to beginning
			if (currentLocation <= START ) {
				// Set status to stop
				setStatus(Animation.PAUSE);

				// Erasing node
				getErasingNode().getSettings().setNodeComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
				getErasingNode().getSettings().setLeftLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
				getErasingNode().getSettings().setRightLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
				((DrawableKey)getErasingNode().getValue()).getSettings().setKeyComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));

				// Draw to animating graphic
				getErasingNode().drawNodeAndLink(g2);

				// Reset location
				currentLocation = 0.0;
			}
			// The fading out of the node.
			else if (currentLocation <= FADE_NODE) {
				float currentAlpha = (float)((double)FADE_NODE - currentLocation);

				// Erasing node
				getErasingNode().getSettings().setNodeComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				getErasingNode().getSettings().setLeftLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				getErasingNode().getSettings().setRightLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				((DrawableKey)getErasingNode().getValue()).getSettings().setKeyComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));

				// Draw to animating graphic
				getErasingNode().drawNodeAndLink(g2);
			}
			// The searching through the tree
			else if (currentLocation == PARTITION_TREE) {

				// Set values for animation
				currentPartition.setStepTime(getStepTime());
				currentPartition.setStep(getStep());

				// Set play status
				currentPartition.setStatus(Animation.REWIND);

				// Draw rotation animation
				currentPartition.drawAnimation(g2, Animation.REWIND);

				if (currentPartition.getStatus().equals(Animation.PAUSE)) {

					messageAction("Cannot Rewind : Beginning of Partition");
					// Pause
					setStatus(Animation.PAUSE);
				}
			}
			// Precautionary (Cannot go beyond FINAL_MOVE)
			else if (currentLocation < FINAL_MOVE) {
				currentLocation = FINAL_MOVE;

				finalMovingNodes.setStatus(Animation.PAUSE);

				messageAction("Cannot Rewind : Beginning of Final Move");
				// Pause
				setStatus(Animation.PAUSE);
			}

			// The final move the nodes
			else if (currentLocation <= END) {
				// Set play status
				finalMovingNodes.setStatus(Animation.REWIND);

				// Set values for animation
				finalMovingNodes.setStepTime(getStepTime());
				finalMovingNodes.setStep(getStep());

				// Draw animation
				finalMovingNodes.drawAnimation(g2, Animation.REWIND);

				if (finalMovingNodes.getStatus().equals(Animation.PAUSE)) {
					messageAction("Cannot Rewind : Beginning of Final Move");
					// Pause
					setStatus(Animation.PAUSE);
				}

			}

		}

		// PAUSE status
		if (getStatus().equals(Animation.PAUSE)) {

			messageAction(Animation.PAUSE);

			// The fading out of the node.
			if (currentLocation < FADE_NODE ) {
				float currentAlpha = (float)((double)FADE_NODE - currentLocation);

				// Erasing node
				getErasingNode().getSettings().setNodeComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				getErasingNode().getSettings().setLeftLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				getErasingNode().getSettings().setRightLinkComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));
				((DrawableKey)getErasingNode().getValue()).getSettings().setKeyComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentAlpha));

				// Draw to animating graphic
				getErasingNode().drawNodeAndLink(g2);

			}
			// The searching through the tree
			else if (currentLocation == PARTITION_TREE) {

				// Set play status
				currentPartition.setStatus(Animation.PAUSE);

				// Draw rotation animation
				currentPartition.drawAnimation(g2, Animation.PAUSE);

			}
			// The rotating up of the node
			else if (currentLocation < END ) {
				finalMovingNodes.setStatus(Animation.PAUSE);
				// Draw animation
				finalMovingNodes.drawAnimation(g2);
			}

		}

		// STOP status
		if (getStatus().equals(Animation.STOP)) {
			messageAction(Animation.STOP);
			// The fading out of the node.
			if (currentLocation < FADE_NODE ) {
				// Do nothing
			}
			// The searching through the tree
			else if (currentLocation == PARTITION_TREE) {

				// Set play status
				currentPartition.setStatus(Animation.STOP);

				// Draw rotation animation
				currentPartition.drawAnimation(g2, Animation.STOP);

			}
			// The rotating up of the node
			else if (currentLocation < END ) {
				finalMovingNodes.setStatus(Animation.STOP);
				// Draw animation
				finalMovingNodes.drawAnimation(g2);
			}

			return;
		}


		// FINISH status
		if (getStatus().equals(Animation.FINISH)) {

			messageAction(Animation.FINISH);

			if (getReplacingNode() == null) {
				messageAction("*--------Deletion of "+getErasingNode().getKey().toString()+"--------*\n"+
							"No Replacement for Node");
			}
			else {
				messageAction("*--------Deletion of "+getErasingNode().getKey().toString()+"--------*\n"+
								"Node replaced by: "+getReplacingNode().getKey().toString());

			}

		}

		// Call listeners
		animationAction();

	}

	/**
	 * Draws a dotted line according to the current location within the graphics.
	 *
	 * @param g2 Graphics2D to which the line is drawn.
	 * @param location the double location of progress in the animation.
	 */
	protected void drawDottedLine( Graphics2D g2, double location) {
		// Makes the left dotted line
		Line2D.Double dottedLeft = new Line2D.Double( (getErasingNode().getCurrentTransform().getTranslateX() + getErasingNode().getCurrentTransform().getScaleX()/2.0 - 1) , (getErasingNode().getCurrentTransform().getTranslateY() + getErasingNode().getCurrentTransform().getScaleY()/2.0) , (getErasingNode().getCurrentTransform().getTranslateX() + getErasingNode().getCurrentTransform().getScaleX()/2.0 - 1) , (g2.getClipBounds().getY() + g2.getClipBounds().getHeight()));
		// Makes the right dotted line
		Line2D.Double dottedRight = new Line2D.Double( (getErasingNode().getCurrentTransform().getTranslateX() + getErasingNode().getCurrentTransform().getScaleX()/2.0+ 1) , (getErasingNode().getCurrentTransform().getTranslateY() + getErasingNode().getCurrentTransform().getScaleY()/2.0) , (getErasingNode().getCurrentTransform().getTranslateX() + getErasingNode().getCurrentTransform().getScaleX()/2.0 + 1) , (g2.getClipBounds().getY() + g2.getClipBounds().getHeight()));

		// Sets break distance
		float dash[] = {10.0f};
	    BasicStroke dashed = new BasicStroke(2.0f,
	                                          BasicStroke.CAP_BUTT,
	                                          BasicStroke.JOIN_MITER,
	                                          10.0f, dash, 0.0f);

		// Draw dotted line.
		if (location <= FADE_NODE) { // Fading in
			g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)location));
		}
		else if (location >= FINAL_MOVE) {
			g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)(1.0 - (location - (Math.floor(location)))) ));
		}
		else {// Full Composite
			g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0F));
		}

		// Set graphics information

		g2.setStroke(dashed);
		g2.setPaint(getLeftLinePaintSettings().getPaint());

		g2.draw(dottedLeft);
		g2.setPaint(getRightLinePaintSettings().getPaint());
		g2.draw(dottedRight);
	}

	/**
	 * Calls all of the listeners of the current Animation and passed information regarding the
	 * progress and status of the current Animation. Additionally, the id of the type of animation is
	 * passed. Within, the <code>animationEventPerformed</code> method is called.
	 *
	 * @param cmd String Animation command passed instead of the current Status.
	 * @param description String description for messages.
	 */
	protected void animationAction(String cmd, String description) {
		super.animationAction(AnimationEvent.DELETE_BST_ANIMATION, cmd, description, currentLocation / END);
	}

	/**
	 * Implements <code>AnimationListener</code> which requires the following method.
	 * The only status of animation it listens for is <code>Animation.ANIMATION_MESSAGE</code>, to pass
	 * the message on.
	 *
	 * @param e AnimationEvent that represents the information of the Animation.
	 */
	public void animationEventPerformed(AnimationEvent e) {

		if (e.getStatus().equals(Animation.ANIMATION_MESSAGE)) {
			messageAction(e.getAnimationDescription());
		}
		if (e.getStatus().equals(Animation.STEP)) {
			animationAction(Animation.STEP, null);
		}

	}

}
