package testprocs;

import simulator.*;
import modules.color.*;
import modules.codegas.*;
import modules.line.*;
import modules.neighborset.*;
import modules.node.*;
import modules.gradient.*;
import utils.*;
import java.awt.*;
import java.util.*;

public class AbyzProc implements ProcessorModule {
  public Symbol getName() { return Symbol.GetSymbol("AbyzProc"); }
  public void link(PortedProcessor p) {
    pp = p;
    pp.addClockListener(this);
    pp.openNetworkPort(this,uiPort);
    cm = (ColorModule)p.getModule("Color");
    ns = (NeighborSet)p.getModule("NeighborSet");
  }


  PortedProcessor pp;
  ColorModule cm; NeighborSet ns;

  static final Symbol uiPort = Symbol.GetSymbol("UI");
  static final Symbol type = Symbol.GetSymbol("abyz");

  public void init() {
    value = flip();
  }

  double flip() { if(Math.random()>0.5) return 1; else return 0; }
  static boolean flip=false;
  static double p = 0.5;
  int timer=0;
  double value;
  boolean flipped = false;

  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("flip")) {
          timer=10; flip=true;
        } else if(cmd.equals("setp")) {
          if(tok.hasMoreTokens()) 
            p = (new Double(tok.nextToken())).doubleValue();
          else
            p = 0.5;
        }
      }
    } else if(name==PortedProcessor.kClock) {
      if(flip && !flipped) {
        value=flip(); ns.setData(type,null); flipped = true; 
      } else if(flipped && !flip) {
        flipped=false;
      }
      if(timer>0) {
        timer--; if(timer==0) flip=false; 
      }

      // formula: value = 1/2(square(value+sum(nbr values)))
      double x = 0; int n=0;
      Iterator i = ns.getNeighbors();
      while(i.hasNext()) { 
        Double d = (Double)ns.getData(type,i.next());
        if(d!=null) { x += d.doubleValue(); n++; }
      }
      if(n>0) x/=n;
      double y = p*value+(1-p)*x;
      double ev = y;
      if(!flip)
        ns.setData(type,new Double(ev));
      
      // coloring
      if(ev < 0.0 || ev > 1.0) cm.setColor(Color.white);
      else if(ev < 0.25) cm.setColor(Color.cyan);
      else if(ev < 0.50) cm.setColor(Color.blue);
      else if(ev < 0.75) cm.setColor(Color.red);
      else if(ev < 1.00) cm.setColor(Color.magenta);
    }
    return dirty;
  }

  public String toString() { return "AbyzProc: ("+value+", "+ns.getData(type)+")";
  }
}
