package testprocs;

import simulator.*;
import modules.color.*;
import modules.gossip.*;
import modules.region.*;
import utils.*;
import java.awt.*;
import java.util.*;

public class GossipTest implements ProcessorModule, Observer {
  public Symbol getName() { return Symbol.GetSymbol("GossipTest"); }
  public void link(PortedProcessor p) {
    pp = p;
    pp.addClockListener(this);
    pp.openNetworkPort(this,uiPort);
    gm = (GossipManager)p.getModule("GossipManager");
    rm = (RegionManager)p.getModule("RegionManager");
    cm = (ColorModule)p.getModule("Color");
  }

  PortedProcessor pp;
  ColorModule cm; GossipManager gm; RegionManager rm;
  static final Symbol uiPort = Symbol.GetSymbol("UI");
  static final Symbol type = Symbol.GetSymbol("GT");

  public void init() {
    gm.addObserver(this);
  }

  int color=-1;
  public boolean signalEvent(Symbol name, Object data) {
    boolean dirty=false;
    if(name==uiPort) {
      StringTokenizer tok = new StringTokenizer(data.toString());
      if(tok.hasMoreTokens()) { 
        String cmd=tok.nextToken();
        if(cmd.equals("color")) {
          int c = 0;
          if(tok.hasMoreTokens()) c=(new Integer(tok.nextToken())).intValue();
          // automatically connect with the first region
          Set s = rm.getRegions(type);
          if(!s.isEmpty()) {
            Object rid = s.iterator().next();
            if(!gm.contains(rid))
              gm.addGossip(rid,type,new VersionGossip(),rid);
            VersionGossip g = (VersionGossip)gm.getGossip(rid);
            g.addObserver(this);
            g.set(new Integer(c));
          }
        } else if(cmd.equals("region")) {
          Symbol s = Symbol.GetSymbol("X");
          if(tok.hasMoreTokens()) s = Symbol.GetSymbol(tok.nextToken());
          if(s.equals("none")) {
            Iterator i = rm.getRegions().iterator();
            while(i.hasNext()) { rm.killRegion(i.next()); }
          } else {
            if(!rm.inRegion(s)) { rm.addRegion(s,type,new LatchedRegion(s)); }
          }
        } else if(cmd.equals("kill")) {
          if(tok.hasMoreTokens()) {
            gm.removeGossip(Symbol.GetSymbol(tok.nextToken()));
          } else {
            Iterator i = gm.getGossip().iterator();
            while(i.hasNext()) { gm.removeGossip(i.next()); }
          }
        }
      }
    } else if(name==PortedProcessor.kClock) {
      // attach to gossips
      Iterator i = gm.getGossip().iterator();
      while(i.hasNext()) {
        Gossip g = gm.getGossip(i.next());
        if(g instanceof VersionGossip) ((Observable)g).addObserver(this);
      }

      // blue if empty, cyan if region, other if colored
      if(rm.getRegions(type).isEmpty()) cm.setColor(Color.blue);
      else if(gm.getGossip().isEmpty()) cm.setColor(Color.cyan);
      else cm.setColor(cm.numberToColor(color));
    }
    return dirty;
  }

  public void update(Observable o, Object arg) {
    if(o instanceof VersionGossip) {
      VersionGossip vg = (VersionGossip)o;
      color = ((Integer)vg.get()).intValue();
    } else if(o instanceof GossipManager) {
      VersionGossip vg = (VersionGossip)((Pair)arg).cdr();
      color = ((Integer)vg.get()).intValue();
    }
  }
}

