import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class TupleSpace extends Applet {

    private MultiHashtable tuples = new MultiHashtable();
    private List display = new List(10); 

    // adds tuple to tuples. tuple.key() is used as key
    public void out(Tuple tuple) {
        tuples.put(tuple.key(),tuple);
        displayKeys();	
    }

    // uses tuple.key() to get and delete matching tuple;
    // passed tuple is replaced by one extracted from tuple space;
    // passed who and value are irrelevant
    // blocks until successful
    public void in(Tuple tuple) {
        Tuple t;
        while ((t = (Tuple) tuples.remove(tuple.key())) == null) {
    	    try {Thread.sleep(100);} 
    	    catch (InterruptedException e){}
    	}
        tuple.setFields(t);    	
        displayKeys();	
    }

    // uses tuple.key() to get and delete matching tuple;
    // passed tuple is replaced by one extracted from tuple space;
    // passed who and value are irrelevant
    // true if success, false otherwise
    public boolean inp(Tuple tuple) {
        Tuple t = (Tuple) tuples.remove(tuple.key());
        if (t != null) {
            tuple.setFields(t);
        }    
        displayKeys();	
        return t != null;
    }

    // uses tuple.key() to get matching tuple;
    // passed tuple is replaced by one read from tuple space;
    // passed who and value are irrelevant
    // blocks until successful
    public void rd(Tuple tuple) {
        Tuple t;
        while ((t = (Tuple) tuples.get(tuple.key())) == null) {
    	    try {Thread.sleep(100);} 
    	    catch (InterruptedException e){}
    	}
        tuple.setFields(t);
    }

    // uses tuple.key() to get matching tuple;
    // passed tuple is replaced by one read from tuple space;
    // passed who and value are irrelevant
    // true if success, false otherwise
    public boolean rdp(Tuple tuple) {
        Tuple t = (Tuple) tuples.get(tuple.key());
        if (t != null) {
            tuple.setFields(t);
        }    
        return t != null;
    }

    // randomly selects one of the TupleSpaceClient applets;
    // invokes its eval service with tuple as arg
    public void eval(Tuple tuple) {
        Vector collection = new Vector();
	    Enumeration e = getAppletContext().getApplets();
	    while (e.hasMoreElements()) {
    		Applet applet = (Applet)e.nextElement();
    		if (applet instanceof TupleSpaceClient) {
    		    collection.addElement(applet);
    		}
    	}
    	if (!(collection.isEmpty())) {
    	    int select = (int) (collection.size()*Math.random());
    	    ((TupleSpaceClient) collection.elementAt(select)).eval(tuple);
    	}	
    }

    public void displayKeys() {
        display.removeAll();
        Enumeration e = tuples.keys();
	    while (e.hasMoreElements()) {
	        String key = (String) e.nextElement();
		    display.add(key + "(" + String.valueOf(tuples.size(key)) + ")");
    	}	
    }

    public void init() {
	    Label label = new Label("Tuple Space Server",Label.CENTER);
        add(label);
        add(display);
    }

    public void paint(Graphics g) {
        g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
    }

    public String getAppletInfo() {
        return "TupleSpace by Charles E. Hughes";
    }

}
