// FormResource.java
// $Id
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.forms ;

import java.io.* ;
import java.net.URLEncoder;
import java.util.* ;

import w3c.www.http.*;
import w3c.jigsaw.http.* ;
import w3c.jigsaw.resources.*;
import w3c.jigsaw.html.HtmlGenerator ;

/**
 * This class implements a high level interface to forms.
 * A FormResource is a resource made of form cards. Each card is made of a
 * set of typed fields. 
 */

public class FormResource extends PostableResource {
    protected static HttpCacheControl CACHE_CONTROL_NOCACHE = null;
    protected static HttpTokenList    PRAGMA_NOCACHE       = null;

    static {
	// Pre-compute the no cache directives:
	CACHE_CONTROL_NOCACHE = HttpFactory.makeCacheControl();
	CACHE_CONTROL_NOCACHE.setNoCache();
	// Pre-compute the no cache directives:
	String nocache[] = { "no-cache" };
	PRAGMA_NOCACHE = HttpFactory.makeStringList(nocache);
    }

    protected Vector vcards  = null ;
    
    /**
     * Lookup an sub resource.
     * Each form card makes its own resource, that's why the 
     * <code>lookup</code> method for this resource is special.
     * @param ls The current lookup state.
     * @return An HTTPResource matching the name to lookup, or
     *    <strong>null</strong> if none was found.
     */

    public boolean lookup (LookupState ls, LookupResult lr) 
	throws HTTPException
    {
	if ( super.lookup(ls, lr) )
	    return true;
	String name = ls.peekNextComponent() ;
	for (int i = 0 ; i < vcards.size() ; i++) {
	    FormCardResource card = (FormCardResource) vcards.elementAt(i) ;
	    if ( card.getName().equals(name) ) {
		// Remove found component from lookup state
		ls.getNextComponent();
		// Setup lookup result:
		lr.setTarget(card);
		return card.lookup(ls, lr);
	    }
	} 
	lr.setTarget(null);
	return false;
    }

    /**
     * Define a new form card, with a specific handler.
     * @param handler The handler for this specific card.
     * @param name The form card name.
     * @param title The form card title.
     */

    public FormCardResource defineCard (FormCardHandler handler
					, String name
					, String title) {
	FormCardResource card = new FormCardResource (this
						      , handler
						      , name
						      , title);
	vcards.addElement (card) ;
	return card ;
    }

    public void renameCard(String oldname, String newname) {
	for (int i = 0 ; i < vcards.size() ; i++) {
	    FormCardResource card = (FormCardResource) vcards.elementAt(i) ;
	    if ( card.getName().equals(oldname) ) {
                card.rename(newname);
		return ;
	    }
	}
    }

    /**
     * Remove a card from the form.
     * @param name The name of the card to remove.
     */

    public void removeFormCard(String name) {
	for (int i = 0 ; i < vcards.size() ; i++) {
	    FormCardResource card = (FormCardResource) vcards.elementAt(i) ;
	    if ( card.getName().equals(name) ) {
		card.delete() ;
		vcards.removeElementAt(i) ;
		return ;
	    }
	}
    }
		
    /**
     * Add some header before the form dumps itself.
     * @param into The html generator to dump the header to.
     */

    public void dumpHeader (HtmlGenerator into) {
	return ;
    }

    /**
     * Add some footer after the form dump.
     * @param into The html generator to dump the header to.
     */

    public void dumpFooter (HtmlGenerator into) {
	return ;
    }

    /**
     * Dump this form content, the given card being selected.
     * @param card The selected card.
     */

    protected void dump (HtmlGenerator g, FormCardResource selected) {
	// Is it time to update our HTML for the card, check it:
	FormCardResource updated = selected.handler.updateFormCard(selected);
	if ( updated != null )
	    selected = updated ;
	// Dump the selected card:
	g.append ("<h1>"+selected.getTitle()+"</h1>") ;
	dumpHeader(g) ;
	selected.dump (g) ;
	g.append ("<hr>") ;
	// Dump the button for card navigation:
	g.append ("<table><tr>") ;
	for (int i = 0 ; i < vcards.size() ; i++) {
	    FormCardResource card = (FormCardResource) vcards.elementAt(i) ;
	    if ( card == selected )
		continue ;
	    // Wrap if more than ten cards:
	    if ((i+1) % 10 == 0 )
		g.append("<tr>");
	    // Dump the card button:
	    String name = card.getName() ;
	    g.append ("<th align=center>") ;
	    g.append ("<a href=\""
                      + getURLPath() 
		      + "/" + URLEncoder.encode(name) + "\">"
                      + name
		      +"</a> ") ;
	    g.append ("</th>") ;
	}
	g.append ("</tr></table>") ;
	dumpFooter(g) ;
    }

    /**
     * Get this form resource.
     * This defaults to get the first card for this resource.
     * @param request The request to process.
     * @exception HTTPException If processing the request failed.
     */

    public Reply get (Request request)
	throws HTTPException
    {
	// Generate the form HTML:
	Reply         r = request.makeReply(HTTP.OK) ;
	HtmlGenerator g = new HtmlGenerator ("form") ;
	dump (g, (FormCardResource) vcards.elementAt(0)) ;
	r.setHeaderValue(r.H_CACHE_CONTROL, CACHE_CONTROL_NOCACHE);
	r.setHeaderValue(r.H_PRAGMA, PRAGMA_NOCACHE);
	r.setStream (g) ;
	return r ;
    }

    public void initialize(Object values[]) {
	super.initialize(values);
	this.vcards  = new Vector() ;
    }

    public FormResource(ResourceContext context, String url) {
	Object values[]     = new Object[attributes.length] ;
	values[ATTR_CONTEXT] = context;
	values[ATTR_URL]    = url ;
	initialize(values) ;
    }

    public FormResource() {
    }

}
