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

// $Id: Transition.java,v 1.6 2003/03/06 00:40:39 moltmans Exp $
// Time-stamp: <2000-03-11 18:59:37 moltmans>
package rec.sys;


////////////////////////////////////////////////////////////////////////////////
//
// FILE:	Transition.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	June, 1998
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Drawing recognition
//
// HISTORY:     September, 1998
//              MDM
//              modified to get ride of the static create constructor
//
//////////////////////////////////////////////////////////////////////////////


import rec.util.*;

/**
 * Contains information about what was done to create the
 *     indicated widget.
 *
 * It can be overridden to contain information about the
 *     widget before the transition.
 *
 * override doUndo(), makeRedoTransition(), and name()
 */
public abstract class Transition
{
  /**
   * use this to create the transition
   */
  public Transition( Surface s )
  {
    m_Id = new Id();
    m_Surface = s;
    m_RedoTransition = null;
  }

  /**
   * An alternative constructor.
   */
 public Transition( Transition redo, Surface s )
  {
    m_Id = new Id();
    m_Surface = s;
    m_RedoTransition = redo;
    redo.m_RedoTransition = this;
  }

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

  public final Id getId()
  {
    return( m_Id );
  }

  public final boolean equals( Transition t )
  {
    return( m_Id.equals( t.getId() ) );
  }

  public boolean equals( Object o )
  {
    if ( o instanceof Transition )
      return equals( (Transition)o );
    else
      return false;

  }


  /**
   * Luke's little hack--do the reverse of the transition.  Should be
   * called "do"
   */
  public void dodo( )
  {
    getRedoTransition().undo();
  }

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

  public final Surface getSurface()
  {
    return( m_Surface );
  }

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

  public final Transition undo()
  {
    doUndo();

    return( getRedoTransition() );
  }

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

  public final Transition getRedoTransition()
  {
    if ( ! isInitialized() )
      m_RedoTransition = makeRedoTransition();

    Assert.check( ( m_RedoTransition.m_RedoTransition == null )
		  || ( m_RedoTransition.m_RedoTransition.equals( this ) ),
		  "Attempting to replace redo transitions with other ones." );

    m_RedoTransition.m_RedoTransition = this;

    return( m_RedoTransition );
  }

  /**
   * Make the transition which undoes this one and return it.
   */
  protected Transition makeRedoTransition( )
  {
    throw new RuntimeException( "makeRedoTransition not defined." );
  }

  /**
   * Undoes the Transition
   */
  public abstract void doUndo();


  /**
   * For debugging, force all transitions to have a name.
   */
  public abstract String name();



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

  private final boolean isInitialized()
  {
    return( !( m_RedoTransition == null ) );
  }

  /**
   * This makes the passed transition the inverse transition for
   * this transition.
   */
  private final Transition setRedoTransition( Transition t )
  {
    Assert.check( ( m_RedoTransition == null ),
		  "Attempting to replace redo transitions with other ones." );
    Assert.check( ( t.m_RedoTransition == null )
		  || ( t.m_RedoTransition.equals( this ) ),
		  "Making an already coupled transition into new couple." );

    t.m_RedoTransition = this;

    return( m_RedoTransition = t );
  }


  public String toString( )
  {
    return name() + ":" + m_Id;
  }

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

  private Id m_Id;
  private Surface m_Surface;
  private Transition m_RedoTransition;
}

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