import java.awt.*;
import java.util.*;

public class ClusterViewer2D extends Frame implements Runnable {
  ClusterWeightedStatePredictor cwms;
  ClusterView cv;

  ClusterViewer2D(ClusterWeightedStatePredictor c){
    cwms = c; 
    add(cv = new ClusterView(cwms));
    doLayout();
    pack();
    show();
    repaint();
  }

  public void run() {
    while(true){
      try { Thread.sleep(500); } catch (Exception e) { }
      repaint();
    }
  }

  public void paint(Graphics g){
    cv.repaint();
  }
  
  public void setScale(double s){
    cv.scale = s;
  }
  public void setOffset(int o){
    cv.offset = o;
  }

}

class ClusterView extends Canvas {
  ClusterWeightedStatePredictor cwsp;
  double scale=1;
  int offset=0;
  private Image offScreenImage;
  private Graphics offScreenGraphics;
  private Dimension offScreenSize;


  ClusterView(ClusterWeightedStatePredictor c){
    cwsp = c;
  }

  public final synchronized void update(Graphics theG){
      Dimension d = size();
      if((offScreenImage == null) || (d.width != offScreenSize.width) ||
         (d.height != offScreenSize.height)) 
        {
          offScreenImage = createImage(d.width, d.height);
          offScreenSize = d;
          offScreenGraphics = offScreenImage.getGraphics();
          offScreenGraphics.setFont(getFont());
        }
      offScreenGraphics.setColor(Color.white);
      offScreenGraphics.fillRect(0,0,d.width, d.height);
      paint(offScreenGraphics);
      theG.drawImage(offScreenImage, 0, 0, null);
  }

  public void paint(Graphics g){
    int clct=0;

    Enumeration e2 = cwsp.states.elements();
    for(Enumeration e = cwsp.feature.elements(); e.hasMoreElements(); ){
      FeatureVector v;
      State s;

      v = ((FeatureVector) e.nextElement());
      s = ((State) e2.nextElement());
      g.setColor(Color.blue);
      g.fillArc((int) (v.vec[0]*scale)-5+offset, (int) (v.vec[1]*scale)-5+offset, 10, 10, 0, 360);
      g.setColor(Color.black);
      g.drawString(s.name, (int) (v.vec[0]*scale)+offset, (int) (v.vec[1]*scale)+offset);

    }
    for(Enumeration e = cwsp.clusters.elements(); e.hasMoreElements(); ){
      Cluster myc;
      myc = ((Cluster) e.nextElement());
      g.setColor(Color.red);
      g.drawString("("+clct+")"+myc.stateString(), (int) (myc.mean[0]*scale)+offset, (int) (myc.mean[1]*scale)+20+offset);
      g.setColor(Color.black);
      g.drawLine((int) (myc.mean[0]*scale)+offset, 
		 (int) ((myc.mean[1]-(myc.variance[1]/4))*scale)+offset, 
		 (int) (myc.mean[0]*scale)+offset, 
		 (int) ((myc.mean[1]+(myc.variance[1]/4))*scale)+offset);
      g.drawLine(
		 (int) ((myc.mean[0]-(myc.variance[0]/4))*scale)+offset, 
		 (int) (myc.mean[1]*scale)+offset, 
		 (int) ((myc.mean[0]+(myc.variance[0]/4))*scale)+offset, 
		 (int) (myc.mean[1]*scale)+offset);
      g.drawArc( (int) ((myc.mean[0]-(myc.variance[0]/4))*scale)+offset, 
		 (int) ((myc.mean[1]-(myc.variance[1]/4))*scale)+offset, 
		 (int) (myc.variance[0]*2*scale/4),
		 (int) (myc.variance[1]*2*scale/4),
		 0, 360);
      clct++;
    }
  }
}
