import netscape_beta.application.*;
import netscape_beta.util.*;

/**
 * A class that displays a DemJava Visitor and it's 
 * set of traversals.
 *
 * @version        1.0 12 Dec 1996
 * @author         Andrew Miller
 */
public class Visitor extends Drawable implements DragSource, Target
{
  // drag and drop support
  private static String dataType = new String("Visitor");
  private DragSession drag = null;
  int downX, downY;
  
  private static VisitorManager m_manager = null;

  // visit attributes
  protected static String BYPASS = new String("bypass");
  protected static String THROUGH = new String("through");
  protected static String END = new String("end");

  // private members
  protected Vector m_traversalList = new Vector(); // should have been a Hash
  protected String m_strCurrentTraversal = null;

    /** Returns run-time type information describing the 
      * object type.
      *
      * @return Always "Visitor"
      */
  public static String dataType()
  {
	 return dataType;
  }

  public static String BYPASS()
  {
	return BYPASS;
  }

  public static String THROUGH()
  {
	return THROUGH;
  }

  public static String END()
  {
	return END;
  }


    /** Set the visitor manager for this visitor.
      * @param manager  The visitor's manager
      */
  public static void setManager(VisitorManager manager)
  {
        m_manager = manager;
  }

    /** Default constructor */
  public Visitor() 
  {
    super();
  }

    /** Construct and display a visitor in the specified view.
      *
      * @param x        Leftmost position of Visitor in view.
      * @param y        Topmost position of Visitor in view.
      * @param nodename Visitor label.
      * @param parent   View in which to draw visitor
      */
  public Visitor(int x, int y, String nodename, View parent)
  {
     super(x,y,nodename, parent);
     setBorder(BezelBorder.loweredButtonBezel());
  }

    /** Set the Visitor color
      *
      * @param color  New color for Visitor
      */
  public void setColor(Color color)
  {
     setBackgroundColor(color);
  }

    /** Handle a mouse click.  Automatically makes this Visitor
      * the VisitorManager's active Visitor before handling the 
      * click.
      *
      * @param event Mouse event.
      */
  public boolean mouseDown(MouseEvent event) 
  {
     downX = event.x;
     downY = event.y;

     // set this visitor active
     m_manager.setActive(this);
     
     // let the superclass do it's thing
     // (possibly display a different traversal)
     super.mouseDown(event);
     return true;
  }
  
    /** Start a drag and drop session.  Displays the visitor image
      * while being dragged
      * @param event Mouse event.
      */
  public void mouseDragged(MouseEvent event)
  {
       if(drag != null)
            return;

       Bitmap bmp = Bitmap.bitmapNamed(new String("visitor.gif"), true);
       drag = new DragSession(this, bmp,
                            0, 0,
                            downX, downY,
                            dataType, this);

  }

    /** End a drag 
      * @param ds Drag session to end
      */
  public void dragWasAccepted(DragSession ds)
  {
     // end the drag
     drag = null;
  }

    /** End a drag 
      * @param ds Drag session to end
      */
  public boolean dragWasRejected(DragSession ds)
  {
     drag = null;
     return true; // animate back to original pos    
  }
    
  public boolean wantsMouseTrackingEvents() {
     return true;
  }

  public View sourceView(DragSession session) {
     return this;
  }

    /**
     * Returns all the traversals for this Visitor that begin from the
     * provided start node.
     *
     * @param startNode     Traversal starting point.
     * @return              Traversals as a DemJava behavior string.
     */
  public String toTraversalString(String startNode)
  {
      String retBuff = new String();

      for  (Enumeration e = m_traversalList.elements(); e.hasMoreElements()  ;)  
      {	
            Traversal trav = (Traversal)e.nextElement();
            
            if(trav.startClassName().equals(startNode))
            {
                retBuff += trav.toTraversalString(this);
            }
      }

      return retBuff; // may be empty
  }

    /**
     * Start node to a traversal from the specified TreeNode.
     *
     * @param start   Start node.
     */
  public void addTraversal(TreeNode start)
  {
      // programatically name the traversal as "<start-node><#traversals>"
      String strTravName = new String(start.getNameForTraversal());
      Integer num = new Integer(m_traversalList.size());
      strTravName += num.toString();
      
      Traversal trav = new Traversal(strTravName);  
      trav.addStartNode(start);

      m_traversalList.addElement(trav);

      // set the active traversal
      setCurrentTraversal(strTravName);

      // show the traversal in the visitor's property sheet
      addProperty(m_strCurrentTraversal, m_strCurrentTraversal);
  }

    /**
     * Update the current traversal.
     *
     * @param newPart   VisitorHost to add to the active traversal.
     * @param parttype  Type of object implementing VisitorHost
     */
  public void updateCurrentTraversal(VisitorHost newPart, String parttype)
  {
        if(m_strCurrentTraversal != null)
        {
            updateTraversal(m_strCurrentTraversal, newPart, parttype);
        }
  }


    /**
     * Update an existing traversal.  Only TreeNodes may end a traversal.
     *
     * @param strTravName   Name of traversal to update.
     * @param newPart       VisitorHost to add to the active traversal.
     * @param parttype      Type of object implementing VisitorHost
     */
  public void updateTraversal(String strTravName, VisitorHost newPart, String parttype)
  {
      for  (Enumeration e = m_traversalList.elements(); e.hasMoreElements()  ;)  
      {	
            Traversal trav = (Traversal)e.nextElement();
            
            if(trav.traversalName().equals(strTravName))
            {
                if(parttype.equals(THROUGH))
                {
                    trav.addThroughNode(newPart);
                }
                else if(parttype.equals(END))
                {
                    TreeNode compare = new TreeNode();
                    if(newPart.hostType() == compare.hostType())
                    {
                        trav.addEndNode((TreeNode)newPart);
                    }
                }
                else if(parttype.equals(BYPASS))
                {
                    trav.addBypassNode(newPart);
                }
            }
      }
  }

    /**
     * Displays or hides the Visitor's current traversal in the provided view.
     *
     * @param view      View in which to display traversal
     * @param bShow     true = show traversal, false = hide traversal
     */
  public void showHosts(View view, boolean bShow)
  {
      for  (Enumeration e = m_traversalList.elements(); e.hasMoreElements()  ;)  
      {	
            Traversal trav = (Traversal)e.nextElement();
            if(trav.traversalName().equals(m_strCurrentTraversal))
            {
                trav.show(this, view, bShow);
            }
      }
  }

   /**
     * Handles selections user makes from Visitor property menu
     * to change the active traversal.
     *
     * Since we generate the commands, we know that the string
     * is guaranteed to be a traversal name (since that's all 
     * that is contained in the visitors property list).
     *
     * @param strProp       The propery command string.
     * @param strCommand    The object sending the command.
     */
  public void performCommand(String string, Object obj)
  {
        super.performCommand(string, obj);

        // Traversal command strings are the same as
        // the property name.
        setCurrentTraversal(string);
  }

  public void setCurrentTraversal(String traversal)
  {
      m_manager.setActive(null);
      m_strCurrentTraversal=traversal;
      m_manager.setActive(this);
  }
}

