import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.applet.*;
import java.util.*;
import java.awt.event.*;

public class FadeImage extends Applet implements Runnable, MouseListener
{
    int opaque = 128; // HUOM! vakio
    int frame_speed, image_sleep, frames;                  
    boolean b = false, bb = true;
    boolean images1 = true, images2 = true;
    Image image[];                             
    Image imgCache[] = new Image[opaque + 1];      
    int opacity, index1 = 0, index2 = 1;                               
    int dxImg, dyImg;                           
    int[] pixels, pixelsImg1, pixelsImg2;        
    Thread th;         
    int[] num;
    MediaTracker tracker;

    String images, status, target, url_string;
    FI fi[];
    int int_u;


           
 public void init()
 {  
    String copyrightParam = getParameter("copyright"); // Suojaus
    if ((copyrightParam == null) || !copyrightParam.equals(copyright))
               throw new SecurityException("Invalid Copyright");

    addMouseListener(this); 
    tracker = new MediaTracker(this);

    for (int i = 0; ;i++)
    {
     if (getParameter("image"+i) == null)
      {
       num = new int[i];

       break;
      }
    }

 image = new Image[num.length];
 fi    = new FI   [num.length];
  
   for(int i = 0; (images = getParameter("image" + i)) != null; i++)
   {
     StringTokenizer st = new StringTokenizer(images, "|");
     
     image[i] = getImage(getDocumentBase(), st.nextToken());
     tracker.addImage(image[i], i);
     try { tracker.waitForID(i); } catch (InterruptedException e) {}

     status = st.nextToken();

     url_string = st.nextToken();

     fi[i] = new FI(this, url_string, status);
     
   } 

 frames = Integer.parseInt(getParameter("frames"));
 frame_speed = Integer.parseInt(getParameter("frames_speed"));
 image_sleep = Integer.parseInt(getParameter("image_sleep"));
 target = getParameter("url_target");

  dxImg = image[0].getWidth(this);
  dyImg = image[0].getHeight(this);

  pixels = new int[dxImg * dyImg]; 
  
     
 }

  public String copyright = 
          "Copyright (c) by Rain Ausmaa";
    
  public void start()
  {
    if (th == null) {
                    th = new Thread(this);
                    th.start();
                     
                    }
  }

 public void stop()
 {
  if (th != null) { th.stop(); th = null;}
  
 }

 int[] grabPixels(Image img) throws InterruptedException
 {
  PixelGrabber pg = new PixelGrabber(img, 0, 0, dxImg, dyImg, true);

        if (pg.grabPixels())
        {
         return (int[])pg.getPixels();
        }
        return null;
 }


 public void run()
 {
  Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
  Runtime.getRuntime().gc();  

  try {

  Graphics g = getGraphics(); 
  int step = 1;

  for (int frame = 0; ; frame+=step)
  {

   if (frame >= frames & images2==true)
       { step=-1; images1=false; index1+=2; int_u = index2; 
         showStatus(fi[setInt()].setStatus());
         Thread.sleep(image_sleep); 
         bb = true;
       }

   if (frame <= 0 & images1==false)		
       { images1=true; step=1; index2+=2; int_u = index1; 
         showStatus(fi[setInt()].setStatus());
         Thread.sleep(image_sleep); 
         bb = true; 
       }

  
   while ((getParameter("image" + index1)) == null) 
   {    
     if(index2 <= 0) { index1 = 1; } else { index1 = 0; }
     int_u = index1; 
   }  

   while ((getParameter("image" + index2)) == null)
   {     
    if(index1 > 0) { index2 = 0; } else { index2 = 1; }
    int_u = index2; 
   }   

   if(bb) // tämä nopeuttaa kuvien latautumista
   {
   pixelsImg1 = grabPixels(image[index1]);
   
   pixelsImg2 = grabPixels(image[index2]);
      
   }
   bb = false;
   
   opacity = opaque - (frame * opaque / frames);
  
   ImageProducer ip = (ImageProducer) new MemoryImageSource(dxImg, dyImg, computeImage(), 0, dxImg);
   prepareImage(imgCache[opacity] = createImage(ip), null);             
              
 if(b)
   {              
    g.drawImage(imgCache[opacity], 0, 0, this);
 
   }
    else
      {
       g.drawImage(image[0], 0, 0, this);
     
       int_u = 0;

       showStatus(fi[int_u].setStatus());

       try { Thread.sleep(image_sleep); } catch (InterruptedException e){};
       b = true;
     }
           	
     Thread.sleep(frame_speed);
  } 
  
   
 } catch (InterruptedException e){}
   
}
   
    public int[] computeImage()
    {
        int rgb1, rgb2;
        int inverse = opaque - opacity;
        for (int idx = pixels.length - 1; idx >= 0; idx--)
        {
            rgb1 = pixelsImg1[idx];
            rgb2 = pixelsImg2[idx];
            
            pixels[idx] = 0xff000000
              | (((((rgb1 & 0x00ff0000) * opacity) +
                   ((rgb2 & 0x00ff0000) * inverse)) >> 7) & 0x00ff0000)
              | (((((rgb1 & 0x0000ff00) * opacity) +
                   ((rgb2 & 0x0000ff00) * inverse)) >> 7) & 0x0000ff00)
              | (((((rgb1 & 0x000000ff) * opacity) +
                   ((rgb2 & 0x000000ff) * inverse)) >> 7) & 0x000000ff);
        }
        return pixels;
    }


  public void mouseExited(MouseEvent me) {}
  public void mouseReleased(MouseEvent me) {}
  public void mouseClicked(MouseEvent me) {}
  public void mouseEntered(MouseEvent me) {}  

  public void mousePressed(MouseEvent me) 
  {
  
  try {

	URL url = new URL(fi[setInt()].setURL());
	getAppletContext().showDocument(url, target);
	  }
	catch (MalformedURLException e) {}
  }

  public int setInt() { return int_u; }

  
}

class FI extends Canvas 
{
 FadeImage fi;
 String status, url_string; 
  
 public FI(FadeImage fi, String url_string, String status) 
 {
  this.fi = fi;
  this.url_string = url_string;
  this.status = status;
  
 }

 public String setURL() { return url_string; }

 public String setStatus() { return status; }


 } 


