// (c) MIT 2003.  All rights reserved.

package rec.fsm;

///////////////////////////////////////////////////////////////////////////////
//
// FILE:	EdgeDup.java
//
// AUTHOR:	Luke Weisman
//              luke@ai.mit.edu
//
// DATE:	June, 1998
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Drawing recognition
//
////////////////////////////////////////////////////////////////////////////////


import java.awt.*;
import java.util.*;
import rec.util.*;
import rec.sys.*;
import rec.geo.*;
import rec.core.widgets.*;

public class EdgeDup extends Edge
{
  private int bend_index;
  private int total_shared;
  boolean flip;

  /**
   * This is used when there is more than one edge going from
   * a node to another node.  Edges get promoted to EdgeDups.
   */
  public EdgeDup( Edge old )
  {
    super( old );

    Assert.check( full(), "EdgeDups need to have 2 connecting nodes." );    
  }


  /**
   * Arrange all the edgedups going from one node to another.
   */
  public void setIndex( )
  {
    //Console.writeln( "Setting index for dups." );
    Vector v = head_node.getEdgesTo( tail_node );

    total_shared = v.size();
    //Console.writeln( "Indexing " + total_shared );
    for ( int i = 0; i < total_shared; i++ )
      {
	Edge ed = (Edge)v.elementAt( i );
	if ( ed instanceof rec.fsm.EdgeDup )
	  {
	    ((EdgeDup)ed).total_shared = total_shared;
	    ((EdgeDup)ed).bend_index = i;

	    // we are going the other way so we need to flip the bend.
	    flip = ! head_node.equals( ed.getNode(true) );

	  }
	else
	  System.err.println("Have edge "+ ed +" in an edgedup connection." );
      }
  }


  /////////////////////////////////////////////////////////////////////////////

  public void draw( Graphics g )
  {
    Color oc = g.getColor();

    g.setColor( Colors.getColor( "edge-full" ) );

    if ( circle() )
      {
	drawCircle( g );
	return;
      }

    GPoint h = getHead(), t = getTail();

    int x = h.getIntX(), y = h.getIntY(), x2 = t.getIntX(), y2 = t.getIntY();
    int xm = ( x + x2 ) / 2;
    int ym = ( y + y2 ) / 2;

    int len = (int)getLength();
    Point d = new Point( x2 - x, y2 - y );
    int dx = d.x * HEAD_SIZE / len;
    int dy = d.y * HEAD_SIZE / len;

    int off = 0;
    off = total_shared - 2 * bend_index - 1;
    if ( flip )
      off *= -1;

    xm += dy * off;
    ym += -1 * dx * off;

    // give the nice thick-line look.
    thickLine( g, x, y, xm, ym );
    thickLine( g, xm, ym, x2, y2 );
    
    if ( arrow_head )
      {
	thickLine( g, x, y, x + dx + -dy, y + dy + dx );
	thickLine( g, x, y, x + dx - -dy, y + dy - dx );
      }

    if ( arrow_tail )
      {
	thickLine( g, x2, y2, x2 - dx + -dy, y2 - dy + dx );
	thickLine( g, x2, y2, x2 - dx - -dy, y2 - dy - dx );
      }

    
    drawNameBubble( (Graphics2D)g, xm, ym );

    g.setColor( oc );
  }


  public void drawCircle( Graphics g )
  {
    GShape tmp = shape;

    int off = 0;
    off = total_shared - 2 * bend_index - 1;
    if (flip )
      off *= -1;
    shape = shape.copy();
    shape.translate( off * 10, 0 );
  
    super.drawCircle(g);

    shape = tmp;
  }



  public Object clone()
  {
    EdgeDup e = new EdgeDup( this );
    e.bend_index = bend_index;
    e.total_shared = total_shared;

    return e;
  }

  

}





