/*

Copyright: All contributers to the Umple Project

This file is made available subject to the open source license found at:
http://umple.org/license

Graph Walking extensions

*/

namespace cruise.umple.compiler;

class Graph 
{
  public boolean hasNext () 
  {
    if (this.stack == null && this.queue == null) return false;
    if (this.isDepthFirst) return stack.isEmpty();
    return this.queue.isEmpty();
  }
}

/*trait Node 
{
  public void visit() 
  { 
    visited = true;
  }

  public boolean isVisited() 
  {
    return visited;
  }
}
*/

class StateMachineLevelGraph 
{

/*
  public StateMachineLevelGraph(UmpleModel model, String name) 
  {
    StateMachine nestedMachine = model.getStateMachine(name);
    if (nestedMachine == null ) return; 

    this.startNode = model.getStartState();
    this.stack = new Stack<Node>();
    this.stack.push(this.startNode);
  }

  public StateMachineLevelGraph(UmpleModel model, String name, boolean isDepthFirst)
  {
      StateMachine nestedMachine = model.getStateMachine(name);
      if (nestedMachine == null) return;

      this.startNode = model.getStartState();

      setIsDepthFirst(isDepthFirst);

      if (isDepthFirst) 
      {
        this.stack = new Stack<Node>();
        this.stack.push(this.startNode);
      } 
      else 
      {
        this.queue = new LinkedList<Node>();
        this.queue.addFirst(this.startNode);
      }
  }
*/
  /**
  * Visit and return the next state in the walk.
  */
  public Node nextNode() 
  {
    if (this.isDepthFirst) return walkDFS();
    return walkBFS();
  }


  private Node walkDFS () 
  { 
    if (this.stack.isEmpty()) return null;
    State state = (State) stack.pop();
    state.visit();
    
    for (Transition transition: state.getTransitions()) 
    {
      State nextState = (State) transition.getNextState();
      // TODO Confirm that the next state is in the same level
      //if (nextState.isInternal() && ! nextState.isVisited()) 
      if (! nextState.isVisited())
      {
        this.stack.push(nextState) ;
      }
    }

    return state;
  }

  private Node walkBFS () 
  {
    if (this.queue.isEmpty()) return null;
    State state = (State) queue.pollLast();
    state.visit();

    for (Transition transition: state.getTransitions()) 
    {
      State nextState = (State) transition.getNextState();
      // TODO Confirm that the state stays in the same level
      //if (nextState.isInternal() && ! nextState.isVisited()) 
      if (! nextState.isVisited())
      {
        this.queue.addFirst(nextState);
      }
    }

    return state;
  }
}


