import java.applet.*;
import java.awt.*;
import java.awt.image.*;

public class WaterCloud extends Applet {
  private Image img, backimg, tree, cloud;
  private MediaTracker track;
  private WaterGrayFilter f;
  private Image gray;
  private Canvas mycanvas,backcanvas;
  private Label rhLabel;
  private Graphics gB, gT;
  private FilteredImageSource fis;
  private Scrollbar enhance;
  private Scrollbar relhum;
  private int enhVal, relhumVal, tempVal; 
  private int xloc, yloc, xsiz, ysiz, xregion, yregion, treeoff;
  private Font labelFont;
  private String[] height={"35,000","30,000","25,000","20,000","15,000",
                          "10,000", " 5,000"," "};
  private String[] temperature ={"-68","-50","-30","-12","  5",
                                 " 23"," 41"," 60"};
                                

  public void init() {


    track = new MediaTracker(this);

    // img = postage stamp image of selected cloud
    img = this.getImage(this.getDocumentBase(), "region5.gif");

    // backimg = GOES IR image
    backimg = this.getImage(this.getDocumentBase(), "vapor.gif");

    // tree = idealized tree and sky
    tree = this.getImage(this.getDocumentBase(), "tree.gif");

    // cloud = little cloud part to move up and down on 'tree'
    cloud = this.getImage(this.getDocumentBase(), "cloud2.gif");

    track.addImage(img,0);
    track.addImage(backimg,0);
    track.addImage(tree,0);
    track.addImage(cloud,0);
    try { track.waitForID(0); }
    catch (InterruptedException ie) {System.out.println("interrupt"+ie);return ;}

    // instantiate the GrayFilter, and define the filtering for img
    f = new WaterGrayFilter();
    fis = new FilteredImageSource(img.getSource(), f) ;
    gray = this.createImage(fis);

    setLayout(null);
    // Pardon the use of constants, but this layout is so
    // specific, that a manager really wasn't needed (or so
    // we hope!)

    enhVal = 35;
    enhance = new Scrollbar(Scrollbar.VERTICAL,enhVal,10,0,240);
    enhance.setValue(enhVal);
    enhance.reshape(740,30,15,270);
    add(enhance);

    relhumVal = 20;
    relhum = new Scrollbar(Scrollbar.HORIZONTAL,relhumVal,10,0,110);
    relhum.setValue(relhumVal);
    relhum.reshape(530,343,150,15);
    add(relhum);

    rhLabel = new Label("xxx",Label.LEFT);
    rhLabel.reshape(700,343,30,15);
    add(rhLabel);

    Font labelFont = new Font("Courier", Font.PLAIN, 12);

    f.setLevel(enhVal, relhumVal);
    setFont(labelFont);

    validate();
    show();

  }

  // paint() redraws the background, the postage stamp, and
  // the lines connecting them.

  public void paint(Graphics g) {
    g.drawImage(backimg,10,30,this);
    g.setColor(Color.green);
    //xloc = 330; yloc = 160;
    //xregion = 220; yregion= 270;
    xloc = 285; yloc = 190;
    xregion = 120; yregion= 280;
    xsiz=img.getWidth(this);
    ysiz=img.getHeight(this);

    g.drawRect(xloc,yloc,17,17);
    g.drawRect(xregion-1,yregion-1,xsiz+1,ysiz+1);

    g.drawLine(xloc,yloc,xregion,yregion);
    g.drawLine(xloc+16,yloc,xregion+xsiz,yregion);
    g.drawLine(xloc+16,yloc+16,xregion+xsiz,yregion+ysiz);
    g.drawLine(xloc,yloc+16,xregion,yregion+ysiz);

    g.setColor(Color.black);
    g.drawString("Air Temperature",680,13);
    g.drawString("(degrees F)",695,25);
    g.drawString("Height",450,13);
    g.drawString("(feet)",450,25);
    g.drawString("Upper Tropospheric Relative Humidity",480,370);
    g.drawString("100%",665,340);
    g.drawString("50%",595,340);
    g.drawString("0%",530,340);

    // for the numeric labels, just plot the 'values' from the arrays
    for (int i=0; i<8; i++) {
      g.drawString(height[i],450,50+(i*32));
      g.drawString(temperature[i],710,50+(i*32));
    }


    // call update() to get the rest of the stuff drawn; this
    // probably could have all been done in paint(), but I
    // needed an excuse to override update (which erases the
    // screen).
    update(g);

  }

  public void update(Graphics g) {
    if (gray != null) {
      g.drawImage(gray,xregion,yregion,this);
    }
    rhLabel.setText(String.valueOf(relhum.getValue())+"%");
    g.drawImage(tree,500,30,this);
    g.drawImage(cloud,570,30+enhVal,this);
  }

  public boolean handleEvent(Event event) {
  	
    if (event.target == enhance) {
      tempVal = enhance.getValue();
      if (tempVal == enhVal) { return true;}
      enhVal = tempVal;

      // if enhVal > 105, then fade into background...
      f.setLevel(tempVal, relhumVal);
      if (gray != null) gray.flush();
      gray = this.createImage(fis);
      update(this.getGraphics());
      return true;
   }
   else if (event.target == relhum) {
      tempVal = relhum.getValue();
      if (tempVal == relhumVal) {return true;}
      relhumVal = tempVal;

      tempVal = enhVal;
      f.setLevel(tempVal, relhumVal);
      if (gray != null) gray.flush();
      gray = this.createImage(fis);
      update(this.getGraphics());

      return true;
   }
     return super.handleEvent(event);
  }
}

// filter the image by modifying all the 'gray' levels (where r=g=b)

class WaterGrayFilter extends RGBImageFilter {
  private int level, relhum;
  private int a,r,g,b,lev;

  public WaterGrayFilter() { 
    canFilterIndexColorModel = true;
  }
  public void setLevel(int lev, int rh) {
    level = 240-lev;
    relhum = (255*rh)/100;
    if (lev > 140) lev = 140;  // 140 is ~15,000 feet
    int pct = (100*(140 - lev))/140;

    if (relhum > 40) {
      level = relhum + pct*(229 - relhum)/100;  // 229 is ~90% rh
    } else {
      level = 40 + pct*(229 - 40)/100;  // 229 is ~90% rh
    }

    if (relhum > 229 && level < relhum) level = relhum;  // no black clouds
    if (lev == 140) level = relhum;  // keep cloud constant for a bit

    //System.out.println("####  lev, rh, level, relhum = "+lev+" "+rh+" "+level+" "+relhum);
  }

  public int filterRGB(int x, int y, int rgb) {

    a = rgb & 0xff000000;
    r = (rgb & 0xff0000) >> 16;
    g = (rgb & 0x00ff00) >> 8;
    b = (rgb & 0x0000ff);
    // only rotate if the image element is gray...

    if (r == b & r == g) {
      if (r >50) {
         r = g = b = level;
      } 
      else { 
         r = g = b = relhum;
      }
    }

    return ( a | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff) );
  }
}
