// DirectoriesEditor.java
// $Id: DirectoriesEditor.java,v 1.10 1997/01/24 12:00:46 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.indexer ;

import java.util.* ;

import w3c.tools.store.*;
import w3c.tools.sorter.*;
import w3c.jigsaw.http.* ;
import w3c.jigsaw.resources.* ;
import w3c.jigsaw.forms.* ;
import w3c.jigsaw.formedit.*;

class DirectoryEditorHandler extends FormCardHandler {
    Directory directory = null;

    public void notifyChange(FormFieldInterface field, Object value) 
	throws FormFieldException
    {
	directory.setValue(field.getName(), value) ;
    }

    DirectoryEditorHandler(Directory directory) {
	this.directory = directory;
    }

}

class DirectoryEditor extends GenericResourceEditor {
    HTTPResource editor = null;

    protected void defineCards() {
	Directory target = (Directory) getTarget();
	FormCardResource card = null;
	card = defineCard(new DirectoryEditorHandler(target)
			  , "Attributes"
			  , "Attributes of Directory template "
			  + target.getIdentifier());
	// Add the generic field:
	FormFieldInterface field = null;
	field = new BooleanField("generic"
				 , "generic"
				 , null
				 , (target.getGenericFlag() 
				    ? Boolean.TRUE
				    : Boolean.FALSE));
	card.addField(field);
	// The class name of the template:
	field = new ClassnameField("class"
				   ,"class"
				   ,null
				   ,target.getTemplate().getClass().getName());
	card.addField(field);
	// Now link field to the template:
	field = new LinkField("template"
			      , "template"
			      , null
			      , getURLPath()+"/template");
	card.addField(field);
    }

    public boolean lookup(LookupState ls, LookupResult lr) 
	throws HTTPException
    {
	if ( ! ls.hasMoreComponents() )
	    return super.lookup(ls, lr);
	String name = ls.peekNextComponent();
	if ( name.equals("template") ) {
	    if ( editor == null ) {
		// Create an editor for the template:
		HTTPResource target = ((Directory) getTarget()).getTemplate();
		Hashtable    defs   = new Hashtable(5);
		defs.put("url", getURLPath()+"/template");
		defs.put("target", target);
		defs.put("parent", this);
		defs.put("server", getServer());
		editor = FormEditorFactory.getEditor(target);
		editor.initialize(defs);
	    }
	    ls.getNextComponent();
	    return editor.lookup(ls, lr);
	} else {
	    return super.lookup(ls, lr);
	}
    }

    public DirectoryEditor() {
    }
    
}

class DirectoriesAddHandler extends FormCardHandler {
    ResourceIndexer indexer = null ;
    String          url     = null ;

    public void notifyButtonClick(String label) {
	indexer.save() ;
    }

    /**
     * We just handle the notification of end of processing.
     */

    public String notifyEndProcessing(FormCardResource card, Request request)
	throws FormProcessingException
    {
	// Get and check the input values:
	String name = (String) card.lookupField("name").getValue() ;
	Class  cls  = (Class) card.lookupField("class").getValue();
	if (name == null) {
	    String msg = "Fill in the name of the directory. If the class is "
		+ " left blank, than this directory will be associated to "
		+ " the DirectoryResource class." ;
	    throw new FormProcessingException (msg) ;
	}
	// Create and register the new directory template:
	Directory d = Directory.makeDirectory(indexer.server, name, cls) ;
	indexer.registerDirectory(d) ;
	// Relocate to the directory template editor:
	return url+"/"+name;
    }

    DirectoriesAddHandler(String url, ResourceIndexer indexer) {
	this.url     = url ;
	this.indexer = indexer ;
    }

}

class DirectoriesListHandler extends FormCardHandler {
    ResourceIndexer indexer = null ;
    Vector          marked  = null ;
    String          url     = null ;

    /**
     * Update the form card.
     * We are really not clever here, this will be improved soon.
     */

    public FormCardResource updateFormCard(FormCardResource card) {
	// Reset the card of all its known fields:
	card.reset() ;
	// Rebuild the fields that are valid now:
	Enumeration enum = indexer.enumerateDirectoryNames() ;
	Vector      exts = Sorter.sortStringEnumeration(enum) ;
	for (int i = 0 ; i < exts.size() ; i ++) {
	    String    name  = (String) exts.elementAt(i) ;
	    FormField field = new CheckBoxField(name
						, name
						, url + "/" + name
						, false);
	    card.addField(field);
	}
	return card ;
    }

    /**
     * On notifyChange, mark directory to be removed.
     */
    
    public void notifyChange(FormFieldInterface field, Object value)
	throws FormFieldException
    {
	if ( marked == null )
	    marked = new Vector() ;
	marked.addElement(field.getName()) ;
    }

    /**
     * On notifyEndProcessing, remove marked directory templates.
     */

    public String notifyEndProcessing(FormCardResource card, Request request)
	throws FormProcessingException
    {
	// No extensions marked ?
	if ( marked == null )
	    return null;
	// Remove all the marked ones
	int vsize = marked.size() ;
	for (int i = 0 ; i < vsize ; i++) {
	    String id = (String) marked.elementAt(i) ;
	    indexer.unregisterDirectory(id) ;
	    card.removeField(id) ;
	}
	marked.setSize(0) ;
	return null ;
    }

    DirectoriesListHandler(String url, ResourceIndexer indexer) {
	this.url     = url ;
	this.indexer = indexer ;
    }
}

public class DirectoriesEditor extends FormResource implements ResourceLocker {
    Hashtable       loaded  = null ;
    ResourceIndexer indexer = null ;

    /**
     * Define the form cards.
     * The directories editor provides one form card for editing the list
     * of known directories, and another one for adding new directories.
     */

    protected void defineFormCards() {
	FormFieldInterface field = null ;
	String             url   = getURLPath() ;

	// The card to remove directories:
	FormCardHandler list_handler = new DirectoriesListHandler(url,indexer);
	FormCardResource c = defineCard(list_handler
					, "Directories"
					, "Defined directories") ;
	c.setOkLabel("Delete");
	list_handler.updateFormCard(c) ;
	// The card to define new directories:
	FormCardHandler add_handler = new DirectoriesAddHandler(url,indexer);
	c = defineCard(add_handler, "Add directory", "Add a new directory.");
	// The input field for the name of the directory:
	field = new TextField("name", "name", null, null) ;
	c.addField(field) ;
	// The input field for the class name:
	field = new ClassnameField("class", "class", null, null) ;
	c.addField(field) ;
	// A Save button:
	c.addButton("Save");
    }

    /**
     * ResourceLocker implementation - The resource is going down.
     * @param resource The resource being brought down.
     */

    public synchronized void notifyResourceLockBreak(Resource resource) {
	loaded.remove(resource.getIdentifier()) ;
    }

    /** 
     * Lookup in the directories editor for a defined directory.
     * @param state The current lookup state object.
     * @return A Resource to edit the directory or <strong>null</strong>.
     */
					    
    public synchronized boolean lookup (LookupState ls, LookupResult lr)
	throws HTTPException
    {
	if ( ! ls.hasMoreComponents() )
	    return super.lookup(ls, lr);
	// Look for an already existing editor, fallback to super otherwise
	String       name   = ls.peekNextComponent() ;
	HTTPResource editor = (HTTPResource) loaded.get(name);
	if ( editor != null ) {
	    ls.getNextComponent() ;
	    lr.setTarget(editor);
	    return editor.lookup(ls, lr);
	}
	// Install a new one
	Directory directory = indexer.loadDirectory(name) ;
	if ( directory == null ) 
	    return super.lookup(ls, lr);
	ls.getNextComponent() ;
	editor = new DirectoryEditor();
	Hashtable defs = new Hashtable(5);
	defs.put("server", getServer());
	defs.put("url", getURLPath()+"/"+name);
	defs.put("target", directory);
	editor.initialize(defs);
	directory.lock(this) ;
	loaded.put(name, editor) ;
	lr.setTarget(editor);
	return editor.lookup(ls, lr);
    }

    /**
     * Initialize the directory templates editor.
     */

    public void initialize(Object values[]) {
	super.initialize(values) ;
	this.indexer = getServer().getIndexer() ;
	this.loaded  = new Hashtable() ;
	defineFormCards() ;
    }

}
