package w3c.jigsaw.admin;

import java.io.*;
import java.util.*;

import w3c.util.*;

import w3c.tools.store.*;
import w3c.www.mime.*;
import w3c.www.http.*;
import w3c.jigsaw.daemon.*;
import w3c.jigsaw.http.*;
import w3c.jigsaw.resources.*;

class ServerHandlerManagerResource extends ContainerResource {
    ServerHandlerManager shm = null;

    public boolean hasResourceStore() {
	return false;
    }

    public ResourceStore getResourceStore(ResourceStoreHolder holder) {
	return null;
    }

    public Resource lookup(String name) {
	ServerHandler handler = shm.lookupServerHandler(name);
	return (handler != null) ? handler.getConfigResource() : null;
    }

    public Enumeration enumerateResourceIdentifiers(boolean all) {
	return shm.enumerateServerHandlers();
    }

    public HTTPResource createDefaultResource(String name) {
	// This should in fact create a new server handler
	return null;
    }

    public void registerResource(String name
				 , HTTPResource child
				 , Hashtable defs) {
	throw new RuntimeException("Can't register resource there !");
    }

    ServerHandlerManagerResource(ServerHandlerManager shm) {
	this.shm = shm;
    }
}

public class AdminServer extends httpd {
    protected ResourceBroker       broker = null;
    protected ServerHandlerManager shm    = null;
    protected AdminWriter          writer = null;
    protected ContainerResource    root   = null;

    public ContainerResource getConfigResource() {
	return root;
    }

    public Reply remoteLoadRoot(Request request) 
	throws HTTPException
    {
	// Dump the root resource:
	ByteArrayOutputStream bout = new ByteArrayOutputStream();
	DataOutputStream      out  = new DataOutputStream(bout);
	try {
	    writer.writeResource(out, root);
	    out.close();
	} catch (IOException ex) {
	    throw new HTTPException("unable to dump root");
	}
	byte bits[] = bout.toByteArray();
	// Setup the reply:
	Reply reply = request.makeReply(HTTP.OK);
	reply.setStream(new ByteArrayInputStream(bits));
	reply.setContentLength(bits.length);
	reply.setContentType(ResourceBroker.conftype);
	return reply;
    }

    public Reply remoteListAttributes(Request request) 
	throws HTTPException
    {
	// Get the name of the class whose attributes are being fetched:
	LookupState ls = new LookupState(request);
	String      cs = ls.getNextComponent();
	// Get this class attributes:
	Class c = null;
	try {
	    c = Class.forName(cs);
	} catch (Exception ex) {
	    ex.printStackTrace();
	    return null;
	}
	// Get the atributes:
	Attribute attrs[] = AttributeRegistry.getClassAttributes(c);
	byte      bits[]  = null;
	try {
	    // Dump them into a byte array:
	    ByteArrayOutputStream bout = new ByteArrayOutputStream();
	    DataOutputStream      out  = new DataOutputStream(bout);
	    writer.writeAttributes(out, attrs);
	    out.close();
	    bits = bout.toByteArray();
	} catch (Exception ex) {
	    ex.printStackTrace();
	    throw new HTTPException("couldn't dump attributes");
	}
	// Emit the appropriate HTP reply:
	Reply reply = request.makeReply(HTTP.OK);
	reply.setContentType(ResourceBroker.conftype);
	reply.setContentLength(bits.length);
	reply.setStream(new ByteArrayInputStream(bits));
	return reply;
    }

    public Reply perform(Request request) 
	throws HTTPException, ClientException
    {
	// Maybe that's one of the methods we handle straight ?
	String mth = request.getMethod();
	if ( mth.equals("LOAD-ROOT") ) {
	    return remoteLoadRoot(request);
	} else if (mth.equals("LIST-ATTRIBUTES")) {
	    return remoteListAttributes(request);
	}
	// Ok, that's targeted toward a specific target resource:
	return broker.perform(request, null);
    }

    public HTTPResource getRoot() {
	return root;
    }

    public void initialize(ServerHandlerManager shm
			   , String identifier
			   , ObservableProperties props)
	throws ServerHandlerInitException
    {
	super.initialize(shm, identifier, props);
	// Create our only resource:
	this.shm = shm;
	writer   = new AdminWriter(this);
	broker   = new ResourceBroker(shm, this, writer);
	root     = new ServerHandlerManagerResource(shm);
    }

    public AdminServer() {
    }
}
