package wbeer.core;

import java.lang.* ;
import java.util.* ;

public class Word extends Vector {
  public static int branch_len = 12 ;
  public static final int max_xpos   = 320 ;
  private static boolean mark[] = new boolean[ max_xpos ] ;
  public Lexicon lex ;

  public String name ;
  public int chainid ;
  public Word parent ;
  public Word left ;
  public Word right ;
  public Word headside ;
  public Word noheadside ;
  public Word assoc ;

  public Word( String name ) {
    clear( name ) ;
  }

  public void add( Feature f ) {
    addElement( f.clone() ) ;
  }

  public Feature get( String id ) {
    Enumeration elem = elements() ;
    Feature f ;

    while( elem.hasMoreElements() ) {
      f = ( Feature )( elem.nextElement() ) ;
      if ( f.id.equals( id ) ) {
        return f ;
      }
    }
    return null ;
  }

  public Object clone() {
    Word w       = ( Word )super.clone() ;
    w.clear( w.name ) ;
    w.parent     = parent ;
    w.left       = left ;
    w.right      = right ;
    w.headside   = headside ;
    w.noheadside = noheadside ;
    w.chainid    = chainid ;
    w.assoc      = assoc ;
    for ( int i = 0 ; i < size() ; i++ ) {
      Feature f = ( Feature )elementAt( i ) ;
      f = ( Feature )f.clone() ;
      f.w = w ;
      w.add( f ) ;
    }
    w.lex = lex ;
    return w ;
  }

  public int NLP( String s ) {
    Parser psr = new Parser() ;
    psr.setLexicon( lex ) ;
    Word w = psr.doParse( s , this ) ;
    if ( w == null ) {
      System.err.println( psr.msg ) ;
      System.err.println( psr.sub ) ;
      return -1 ;
    } else {
      return w.wbMain( null ) ;
    }
  }

  public String toString() {
    StringBuffer buf = new StringBuffer( "[" + name + "]\n" ) ;
    Enumeration elem = elements() ;

    while( elem.hasMoreElements() ) {
      buf.append( ( ( Feature )elem.nextElement() ).toString() + "\n" ) ;
    }
    return buf.toString() ;
  }

  public void clear( String name ) {
    removeAllElements() ;
    this.name  = name ;
    this.lex   = lex ;
    parent     = null ;
    left       = null ;
    right      = null ;
    headside   = null ;
    noheadside = null ;
    chainid    = -1 ;
    assoc      = null ;
    lex        = null ;
  }

  public boolean isGoverned() {
    return ( parent != null ) ;
  }

  public boolean isGovernor( Word w ) {
    if ( w == null ) {
      return false ;
    }

    if ( this == w ) {
      return true ;
    }

    if ( this.noheadside == w ) {
      return true ;
    }

    if ( headside != null ) {
      return headside.isGovernor( w ) ;
    }
    return false ;
  }

  public boolean isUpperSide( Word w ) {
    if ( w == null ) {
      return false ;
    }
    if ( this == w ) {
      return false ;
    }
    if ( this.right == w ) {
      return true ;
    }

    if ( this.left == w ) {
      return true ;
    }

    if ( right != null ) {
      if ( right.isUpperSide( w ) ) {
        return true ;
      }
    }
    if ( left != null ) {
      if ( left.isUpperSide( w ) ) {
        return true ;
      }
    }
    return false ;
  }

  public boolean rightDownFrom( Word w ) {
    while ( w != null ) {
      if ( this == w ) {
        return true ;
      }
      w = w.right ;
    }
    return false ;
  }

  public String treeImage( int offset , boolean fval ) {
    offset = offset / branch_len ;
    Integer ic = new Integer( offset ) ;
    for ( int i = 0 ; i < max_xpos ; i++ ) {
      mark[ i ] = false ;
    }
    return treeImage( ic , fval ) ;
  }

  private String treeImage( Integer ic , boolean fval ) {
    int i , count , mypos ;
    Feature f ;
    boolean Word_checked ;
    StringBuffer buf = new StringBuffer() ;
    int pre_branch  = branch_len / 2 ;
    int post_branch = branch_len / 2 ;
    if ( pre_branch + post_branch == branch_len ) {
        pre_branch-- ;
    }

    count = ic.intValue() ;
    mypos = count * branch_len + pre_branch ;

    if ( count > 0 && ( parent == null ||
       ( ( parent.right == this ) && ( parent.left != null ) ) ) ) {
        for ( i = 0 ; i < ( ( count - 1 ) * branch_len + pre_branch ) ; i++ ) {
          if ( ( i < max_xpos ) && ( mark[ i ] ) ) 
            buf.append( '|' ) ;
          else {
            buf.append( ' ' ) ;
          }
        }
        if ( parent != null ) {
          buf.append( '+' ) ;
          for ( i = 0 ; i < post_branch ; i++ ) {
            if ( assoc == null ) {
              buf.append( '-' ) ;
            } else {
              buf.append( '.' ) ;
            }
          }
        } else {
          buf.append( ' ' ) ;
          for ( i = 0 ; i < post_branch ; i++ ) {
            buf.append( ' ' ) ;
          }
        }
    }

    count++ ;
    ic = new Integer( count ) ;

    if ( left == null && right == null ) {
      buf.append( name ) ;
      if ( chainid >= 0 ) {
        buf.append( '_' + String.valueOf( chainid ) ) ;
      }
      if ( fval ) {
        Word mp = maxproject() ;
        Word_checked = false ;
        for ( i = 0 ; i < mp.size() ; i++ ) {
          f = ( Feature )mp.elementAt( i ) ;
          if ( f.checked ) {
            if ( Word_checked == false ) {
              Word_checked = true ;
              buf.append( ";" ) ;
            }
            buf.append( ' ' + f.name + '(' + f.value + ')' ) ;
          }
        }
      }
      buf.append( '\n' ) ;
      count-- ;
      ic = new Integer( count ) ;
    } else {
      int len = 0 ;
      buf.append( name ) ;
      if ( chainid >= 0 ) {
        buf.append( '_' + String.valueOf( chainid ) ) ;
        len += String.valueOf( chainid ).length() + 1 ;
      }
      len += name.length() ;

      for( ; len < branch_len ; len++ ) {
        buf.append( '-' ) ;
      }

      if ( ( mypos > 0 ) && ( mypos < max_xpos ) ) {
          mark[ mypos ] = right != null ;
      }

      if( left != null ) {
        buf.append( left.treeImage( ic , fval ) ) ;
      }

      if ( ( mypos > 0 ) && ( mypos < max_xpos ) ) {
          mark[ mypos ] = false ;
      }

      if( right != null ) {
        buf.append( right.treeImage( ic , fval ) ) ;
      }
      count-- ;
      ic = new Integer( count ) ;
    }
    return buf.toString() ;
  }

  public Word maxproject() {
    Word mp = this ;
    while ( mp.parent != null && mp.parent.headside == mp ) {
      mp = mp.parent ;
    }
    return mp ;
  }

  public Word rightmost() {
    if ( right == null ) {
      return this ;
    }
    return right.rightmost() ;
  }

  public Word leftmost() {
    if ( left == null ) {
      return this ;
    }
    return left.leftmost() ;
  }

  protected int eval( String fname , String args[] ) {
    Feature f = get( fname ) ;
    if ( f.checked ) {
      f.nohead.wbMain( args ) ;
    }
    return 0 ;
  }

  protected Word f2w( String fname ) {
    Feature f = get( fname ) ;
    if ( f.checked ) {
      return f.nohead ;
    }
    return null ;
  }

  public int wbMain( String args[] ) {
    return 0 ;
  }
}

