package Algorithms.Animated.BK;

import Algorithms.Animated.AlgorithmStage;
import Algorithms.Animated.AnimatedAlgorithm;
import Algorithms.Animated.AnimationController;
import Model.LayeredGraphNode;

/**
 * The main stage of the BK node placement algorithm.
 * @author kolja
 *
 */
public class BKNodePlacement extends AnimatedAlgorithm {

	/*
	 * Private data structures to store the process of the algorithm
	 */
	
	private enum State
	{
		LAYOUT1,
		LAYOUT2,
		LAYOUT3,
		LAYOUT4,
		COMBINE
	}
	
	private State state;
	private ExtremalLayoutCalc layouts[];
	private Combine combine;
	
	public BKNodePlacement(AnimationController controller, LayeredGraphNode graph) {
		super(controller, graph);
		state = State.LAYOUT1;
		layouts = new ExtremalLayoutCalc[ 4 ];
		layouts[ 0 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_LEFT, graph );
		layouts[ 1 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_RIGHT, graph );
		layouts[ 2 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.BOTTOM_TOP_LEFT, graph );
		layouts[ 3 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.BOTTOM_TOP_RIGHT, graph );
		combine = new Combine( graph );
	}

	@Override
	public StageStatus forwardStep() {
		switch( state )
		{
		case LAYOUT1:
			if( layouts[ 0 ].forwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT2;
			break;
		case LAYOUT2:
			if( layouts[ 1 ].forwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT3;
			break;
		case LAYOUT3:
			if( layouts[ 2 ].forwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT4;
			break;
		case LAYOUT4:
			if( layouts[ 3 ].forwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.COMBINE;
			break;
		case COMBINE:
			return combine.forwardStep();
		}
		return StageStatus.UNFINISHED;
	}

	@Override
	public StageStatus backwardStep() {
		switch( state )
		{
		case LAYOUT1:
			return layouts[ 0 ].backwardStep();
		case LAYOUT2:
			if( layouts[ 1 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT1;
			break;
		case LAYOUT3:
			if( layouts[ 2 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT2;
			break;
		case LAYOUT4:
			if( layouts[ 3 ].backwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT3;
			break;
		case COMBINE:
			if( combine.backwardStep() == AlgorithmStage.StageStatus.FINISHED )
				state = State.LAYOUT4;
			break;
		}
		return StageStatus.UNFINISHED;
	}
}
