package animation;

import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingUtilities;

import animation.PseudoCodeProcessor.CodeStatus;
import graph.LayeredGraphNode;

public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage {

    protected AnimationController ac;
    protected LayeredGraphNode graph;
    private JFrame view;
    protected PseudoCodeNode root;
    protected PseudoCodeProcessor processor;

    public AnimatedAlgorithm( AnimationController controller, LayeredGraphNode graph, JFrame view )
    {
        this.ac = controller;
        this.graph = graph;
        this.view = view;
        root = null;
    }

    private void update()
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                view.repaint();
                for( ComponentListener l : view.getComponentListeners() )
                {
                    l.componentResized( new ComponentEvent(view, 0) );
                }
            }
        });
    }

    @Override
    public void run()
    {
        while( true ) // if this loop would end we could not undo steps any more
        {
        	CodeStatus status = null;
            try {
                if( processor != null )
                {
                    switch( ac.getNextAction() )
                    {
                    case FORWARD:
                    	status = processor.forwardStep();
                        break;
                    case FORWARD_OUT:
                        status = processor.forwardStepOut();
                        break;
                    case FORWARD_OVER:
                        status = processor.forwardStepOver();
                        break;
                    case BACKWARD:
                        status = processor.backwardStep();
                        break;
                    case BACKWARD_OUT:
                        status = processor.backwardStepOut();
                        break;
                    case BACKWARD_OVER:
                        status = processor.backwardStepOver();
                        break;
                    }
                }
                else
                    status = CodeStatus.FINISHED;
            } catch (InterruptedException e) {
                e.printStackTrace();
                return;
            }
            update();
            if( status == CodeStatus.FINISHED )
            {
        		ac.setContinuous( false );
        		ac.setNextAction( null );
            }
        }
    }

    @Override
    public abstract PseudoCodeNode createPseudocodeTree( JTree tree );
    
    public PseudoCodeProcessor getProcessor() {
        return processor;
    }
    
    public String getDebugString()
    {
        if( processor == null )
            return "";
        return processor.getDebugOutput();
    }
}
