// IPTemplatesField.java
// $Id: IPTemplatesField.java,v 1.2 1996/07/15 15:03:18 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.auth;

import java.util.*;

import w3c.jigsaw.forms.*;
import w3c.jigsaw.html.HtmlGenerator ;

/**
 * A form field to edit a list pf IP templates.
 * This field allows you to edit a series of IP templates as a list (in the
 * form sense of a list) of ip templates.
 * <p>Each IP templates is made of a dot separated list of four byte values,
 * some of them possibly being stars (to denote that any values for the 
 * remaining bytes will be accepted).
 */

public class IPTemplatesField extends FormField {
    short  value[][] = null ;
    String strval    = null ;

    /**
     * Parse the given string as an IP template, and add into.
     * @param str The string to parse.
     * @param into The vector to put the result to.
     * @exception FormFieldException If we weren't able to parse the string.
     */

    protected short[] parseIPTemplate(String str) 
	throws FormFieldException
    {
	short   ip[]       = new short[4] ;
	int     ipptr      = 0 ;
	boolean wildcarded = false ;
	int     idx        = 0 ;
	int     strlen     = str.length() ;

	while ( idx < strlen ) {
	    if ( str.charAt(idx) == '*' ) {
		idx++;
		ip[ipptr++] = 256 ;
		wildcarded = true ;
	    } else if (( ! wildcarded) && Character.isDigit(str.charAt(idx))) {
		int bstart = idx ;
		do {
		    idx++ ;
		} while ((idx < strlen) && Character.isDigit(str.charAt(idx)));
		String bval = str.substring(bstart, idx) ;
		int    b    = 0;
		try {
		    b = Integer.parseInt(bval);
		} catch (NumberFormatException ex) {
		    String msg = "Invalid IP address byte: "+bval+" in "+str;
		    throw new FormFieldException (msg) ;
		}
		if ( b > 255 ) {
		    String err = "Invalid IP "+bval+" too bog.";
		    throw new FormFieldException(err);
		}
		ip[ipptr++] = (short) (Integer.parseInt(bval) & 0xff);
	    }  else {
		String msg = "Invalid IP template: "+str;
		throw new FormFieldException(msg) ;
	    }
	    if ( ipptr == 4 ) {
		return ip ;
	    } else if (str.charAt(idx++) != '.') {
		throw new FormFieldException("Invalid IP template: "+str) ;
	    }
	}
	throw new FormFieldException ("Invalid IP template: "+str) ;
    }

    /**
     * Parse the array of strings into an array of ip templates.
     * @param str The string to parse.
     * @exception FormFieldException If the value can't be parsed properly.
     */

    protected short[][] parseString(String str)
	throws FormFieldException
    {
	// Unset the field's value.
	if ( str == null )
	    return null ;
	// Parse the strings
	int    idx   = 0 ;
	int    lst   = 0 ;
	Vector items = new Vector() ;
	for ( ; idx < str.length() ; idx++ ) {
	    if (str.charAt(idx) == '\n') {
		if ( lst < idx )
		    items.addElement(parseIPTemplate(str.substring(lst, idx)));
		lst = idx + 1 ;
	    } 
	} 
	// Don't forget last item:
	if ( lst < idx )
	    items.addElement(parseIPTemplate(str.substring(lst, idx)));
	short ips[][] = new short[items.size()][] ;
	items.copyInto(ips) ;
	return ips ;
    }

    /**
     * Compute the string value of the text area for this ip template.
     */

    private void appendIPTemplate(short ip[], StringBuffer into) {
	for (int i = 0 ; i < ip.length ; i++) {
	    if ( i > 0 )
		into.append('.');
	    if (ip[i] == 256)
		into.append("*");
	    else
		into.append(ip[i]);
	}
	return ;
    }

    protected String computeString(short ip[][]) {
	if ( ip == null )
	    return "";
	StringBuffer sb = new StringBuffer() ;
	int i = 0 ;
	for ( ; i < ip.length ; i++) {
	    appendIPTemplate(ip[i], sb) ;
	    sb.append("\r\n");
	}
	return sb.toString() ;
    }	    
		
    /**
     * Get this field's value.
     * @return An array of array of shorts or <strong>null</strong>.
     */

    public Object getValue() {
	return value ;
    }

    /**
     * Set this field value to the given string format IP template address.
     * @param nval The new string value.
     */

    public boolean setValue(String nval)
	throws FormFieldException
    {
	// Unset the field's value ?
	if ((nval == null) || nval.equals("")) {
	    boolean result = (value != null) ;
	    value  = null ;
	    strval = null ;
	    return result ;
	}
	// fast-check new value, or parse the 'new' value
	if ( nval.equals(strval) )
	    return false ;
	short ip[][] = parseString(nval) ;
	if ( ip == null ) {
	    boolean result = (value != null);
	    value  = null ;
	    strval = null ;
	    return result ;
	}
	// Check for a new value:
	if ((value != null) && (ip.length == value.length)) {
	    boolean differs = false ;
	  loop:
	    for (int i = 0 ; i < ip.length ; i++) {
		for (int j = 0 ; j <4 ; j++) {
		    if (ip[i][j] != value[i][j]) {
			differs = true ;
			break loop ;
		    }
		}
	    }
	    if ( ! differs )
		return false ;
	}
	// Set the value:
	value  = ip ;
	strval = nval ;
	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=\""
			 + getName()
			 + "\" rows=\""
			 + Math.min(value.length+3, 6) 
			 + "\">") ;
	    into.append(strval) ;
	    into.append("</textarea></th>") ;
	} else {
	    into.append("<th align=left>"
			+ "<textarea name=\""+getName()+"\" rows=\"5\">"
			+ "</textarea></th>") ;
	}
    }


    public void initialize(String name, String title, String url, Object value)
	throws FormFieldException
    {
	super.initialize(name, title, url, null) ;
	try {
	    this.value = (short[][]) value;
	} catch (ClassCastException ex) {
	    throw new FormFieldException ("invalid init value.");
	}
	this.strval = computeString(this.value) ;
    }

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

    public IPTemplatesField() {
    }

}
