// TextArrayField.java
// $Id: TextArrayField.java,v 1.2 1996/09/25 14:14:48 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.forms;

import java.util.* ;

import w3c.jigsaw.html.HtmlGenerator ;

public class TextArrayField extends FormField {
    Object value  = null;
    protected String strval = null ;

    /**
     * Get this field's value.
     */

    public Object getValue() {
	return value ;
    }

    /**
     * Parse the given \r or \n sparated list of items into an array of items.
     * @param str The string to parse.
     * @return An array of String.
     */

    protected Object parseString(String str) {
	StringTokenizer st      = new StringTokenizer(str, "\r\n") ;
	int             count   = st.countTokens();

	// Check for null value:
	if ( count == 0 )
	    return null ;
	// get all the tokens:
	String items[] = new String[count] ;
	for (int iptr = 0 ; iptr < count ; iptr++) 
	    items[iptr] = st.nextToken() ;
	return items ;
    }

    /**
     * Compute the string to display for the given list of items
     */

    protected String computeString(Object val) {
	String items[] = (String[]) val;
	if ( items == null )
	    return null ;
	StringBuffer sb = new StringBuffer() ;
	int i = 0 ;
	for ( ; i < items.length - 1 ; i++) 
	    sb.append(items[i]+"\n") ;
	sb.append(items[i]) ;
	return sb.toString() ;
    }

    protected boolean differs(Object v1, Object v2) {
	String strs1[] = (String[]) v1;
	String strs2[] = (String[]) v2;
	if ((strs1 == null) && (strs2 == null))
	    return false;
	if ((strs1 != null) && (strs1.length == strs2.length)) {
	    boolean differs = false ;
	    for (int i = 0 ; i < strs1.length ; i++) {
		if ( ! strs1[i].equals(strs2[i]) ) 
		    return true;
	    }
	    return false;
	}
	return true;
    }

    /**
     * Set this field's value to the given String.
     * The string is parsed, each line makes one entry in the array of text.
     * @param nval The new value, as a single String to be parsed.
     * @return A boolean, <strong>true</strong> indicates that the field's 
     *    value has changed.
     * @exception FormFieldException If the provided value didn't match the
     *    expected type.
     */

    public boolean setValue(String nval)
	throws FormFieldException
    {
	// Has the value been reset:
	if ((nval == null) || nval.equals("") ) {
	    boolean result = (value != null) ;
	    value  = null ;
	    strval = null ;
	    return result ;
	}
	// Fast-check for a value change, than parse the new value:
	if ((strval != null) && nval.equals(strval))
	    return false ;
	Object parsed = parseString(nval) ;
	if (parsed == null) {
	    boolean result = (value != null);
	    value  = null ;
	    strval = null ;
	    return result ;
	}
	// Slow check for a value change:
	if (value != null) {
	    if ( ! differs(parsed, value) )
		return false;
	}
	// Update the value:
	value  = parsed;
	strval = nval ;
	return true ;
    }

    /**
     * Set this field's value.
     * @param value The new value for the field.
     */

    public boolean setValue(String value[]) {
	this.value = value ;
	return true ;
    }

    /**
     * Dump this fieldas a form element.
     * @param into The HtmlGenerator to dump the field to.
     */

    public void dump (HtmlGenerator into) {
	dumpTitle(into) ;
	if ( value != null ) {
	    into.append ("<th align=left><textarea name=\""+name+"\" rows=\""
			 + 4
			 + "\">") ;
	    into.append(strval);
	    into.append("</textarea></th>") ;
	} else {
	    into.append("<th align=left>"
			+ "<textarea name=\""+name+"\" rows=\"5\">"
			+ "</textarea></th>") ;
	}
    }

    /*
     * Initialize a TextArrayField.
     * @param name The name of the field.
     * @param title Its title.
     * @param url Its url (or <strong>null</strong>).
     * @param value Its default value.
     * @exception FormFieldException If the provided value doesn't match 
     *    the expected type.
     */
    
    public void initialize(String name, String title, String url, Object val) 
	throws FormFieldException
    {
	super.initialize(name, title, url, null) ;
	try {
	    this.value = (String[]) val ;
	} catch (ClassCastException ex) {
	    String msg = "Invalid type: "+val.getClass().getName() ;
	    throw new FormFieldException (msg) ;
	}
	this.strval = computeString(this.value) ;
    }


    public TextArrayField(String name, String title, String url) {
	super(name, title, url);
    }

    public TextArrayField (String name, String title, String url
			  , String value[]) {
	super(name, title, url) ;
	this.value  = value ;
	this.strval = computeString(this.value) ;
    }

    public TextArrayField() {
    }

}
