package codelines;

import animation.CodeLine;
import animation.ControlFlow;
import animation.Memory;
import animation.Memory.MemoryType;
import animation.StackFrame;
import animation.StackFrame.FrameType;

public class FunctionDefinition extends CodeLine {

	private String[] params;
	
	public FunctionDefinition( String[] params )
	{
		this.params = params;
	}
	
	@Override
	public ControlFlow runForward(Memory m) {
		if( !m.isDefined( "line_" + lineId + "_inside", MemoryType.LOCAL ) )
		{
			m.addFrame( new StackFrame( FrameType.FUNCTION ) );
			m.declare( "line_" + lineId + "_inside", true, MemoryType.LOCAL );
			int index = 1;
			Object olds[] = new Object[ params.length ];
			for( String p : params )
			{
				olds[ index - 1 ] = m.read( "param" + index, MemoryType.GLOBAL );
				m.declare( p, olds[ index - 1 ], MemoryType.LOCAL );
				m.undeclare( "param" + index, MemoryType.GLOBAL );
				index++;
			}
			actions.push( (Memory mem) -> {
				mem.removeFrame();
				int i = 1;
				for( @SuppressWarnings("unused") String p : params )
				{
					mem.declare( "param" + i, olds[ i - 1], MemoryType.GLOBAL );
					i++;
				}
			} );
			return new ControlFlow( ControlFlow.STEP_INTO );
		}
		else
		{
			StackFrame frame = m.removeFrame();
			actions.push( (Memory mem) -> {
				mem.addFrame( frame );
			} );
			return new ControlFlow( ControlFlow.STEP_OVER ); // return
		}
	}
}
