/*
 *  @# ImageLoader.java 1.0 96/9/20
 *  Copyright (c) 1996 Lawrence Rodrigues
 */
import java.io.*;
import java.awt.*;
import java.util.*;
import java.net.URL;
import java.awt.image.*;

public class  ImageLoader extends Object implements ImageObserver{
   //public Image  image;
   //public int width = -1, height = -1;
   //public int origPixels[];
   //public ColorModel cm;
   public URL url= null;
   public String fileName = null;
   public String dir;
   public String imageName;
   //public int imageId;
   public int loadStatus = ImageLoadedListener.EMPTY;
   Vector ils = new Vector();
   ImageBuffer imageBuffer = new ImageBuffer();


   public ImageLoader(){
      loadStatus |= ImageLoadedListener.EMPTY;
   }
   
   public ImageBuffer getImageBuffer() {
      return imageBuffer;
   }

   public void setWidHt(int wd,  int ht){
      //width = wd; height = ht;
      imageBuffer.setWidHt(wd, ht);
      loadStatus |= ImageLoadedListener.HT_WID_KNOWN;
   }

   public void setParams(int rwIm[], int wd, int ht, ColorModel colCm){
      //width = wd; height = ht;
      //cm = colCm;
      //origPixels = rwIm;
      imageBuffer.setParams(rwIm, wd, ht, colCm);
      loadStatus |= (ImageLoadedListener.LOAD_REQUESTED | 
                     ImageLoadedListener.HT_WID_KNOWN| 
                     ImageLoadedListener.PIXELS_AVAILABLE);
   }

   public void setFileInfo(String path, String name, int id){
      if(path == null || name == null) return;
      dir = path;
      imageName = name;
      //imageId = id;
      fileName = new String(dir+File.separatorChar+imageName);
      url = null;
      imageBuffer.setFileInfo(path, fileName, id);
   }

   public  void setUrlInfo(URL ul, String name, int id){
      if(ul == null || name == null) return;
      url = ul;
      imageName = name;
      //imageId = id;
      fileName = null;
      imageBuffer.setUrlInfo(ul, fileName, id);

   }
   public  boolean requestImageLoad(){
      if((url == null) && (dir == null)) return false;
      Image image = null;

      if(url != null) image = Toolkit.getDefaultToolkit().getImage(url);
      if(fileName != null) image = Toolkit.getDefaultToolkit().getImage(fileName);
      imageBuffer.image = image;
      if(image == null) return false;
      return true;
   }

   public  boolean fetchWidHt(){
      if(imageBuffer.image == null) return false;
      int wid = imageBuffer.image.getWidth(this);
      int ht = imageBuffer.image.getHeight(this);
      if((wid == -1) || (ht == -1)) return false;
      setWidHt(wid, ht);
      imageBuffer.setWidHt(wid, ht);
      return true;
   }

   public  void load(){
      if(loadStatus == ImageLoadedListener.EMPTY){
         if(!requestImageLoad()) return ;
      }
      fetchWidHt();
   }

   public boolean fetchPixels(){
      int width = imageBuffer.width;
      int height =  imageBuffer.height;
      if((width <0) || (height<0)){
         load();
         return false;
      }
      int pixMap[] = new int[width*height];
      PixelGrabber pg = new PixelGrabber(imageBuffer.image, 0,0,width,height, pixMap, 0, width);
      try {
	   pg.grabPixels();
      } catch (InterruptedException e){return false;}
      if((pg.status()  & ImageObserver.ABORT)!=0){
          loadStatus = ImageLoadedListener.ERRORED;
          fireImageLoadedEvent();
          return false;
      }
      setParams(pixMap, width, height, imageBuffer.cm);
      fireImageLoadedEvent();
      return true;
   }

   /** Prepares the image to be constructed with its original width & height
    */ 
   public boolean prepareImage(){
      return prepareImage(imageBuffer.width, imageBuffer.height);
   }

   /** Prepares the image to be constructed with a given width and height.
    */ 
   public boolean prepareImage(int wid, int ht ){
      if(imageBuffer.image == null) return false;
      if(Toolkit.getDefaultToolkit().prepareImage(imageBuffer.image, wid, ht, this)){
         loadStatus |= ImageLoadedListener.IMAGE_READY;
      }
      return true; 
   }
    /** Implements ImageObserver interface. Called at regular intervals when
      * image related operations are taking place. This methods notifies the
      * clients when a certain status becomes avaialale.
      */
   public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height){
      if((infoflags & ImageObserver.ERROR) != 0){
         loadStatus = ImageLoadedListener.ERRORED;
         return false;
      }
      if((infoflags & (ImageObserver.WIDTH | ImageObserver.HEIGHT))!= 0){
          setWidHt(width, height);
          fireImageLoadedEvent();
      }
      if((infoflags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS))!= 0)           {
          loadStatus |= ImageLoadedListener.IMAGE_READY;
          fireImageLoadedEvent();
          return false;
       }
       return true;
   }

   public void addImageLoadedListener(ImageLoadedListener il) {
      ils.addElement(il);
   }

   public void removeImageLoadedListener(ImageLoadedListener il) {
      ils.removeElement(il);
   }

   /** Notifies all the registered client objects.
     */
   public void  fireImageLoadedEvent(){
      for(Enumeration e = ils.elements() ; e.hasMoreElements() ;) {
          ImageLoadedEvent ilevent = new ImageLoadedEvent(this, imageBuffer.image, loadStatus);
          ((ImageLoadedListener)(e.nextElement())).imageLoaded(ilevent);
       }
   }
}

