/** (C) 1999 World Xiangqi League, Confidential, All Rights Reserved */

import java.net.*;
import java.awt.*;
import java.applet.*;
import java.awt.Image;
import sun.awt.image.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;

class SponsorCanvas extends Canvas implements Runnable {
  private static final int ADSEC = 60; // num seconds between ads
  private static final int ADW = 200, ADH=80;  // max ad dimensions
  private Vector gifs, imgs, urls; // local RAM cache
  private int displayed=0, desired=0, loaded=0; // banner indices
  private int viewed=1, clicked=0; // stats viewed/clicked so far
  private Club club;
  private Thread thread;	// timer: new banner every 60 seconds

  SponsorCanvas(Club club) {
    super();
    resize(ADW,ADH+2);		// Club sponsor banner size
    this.club = club;
    setup();			// load the banner campaign
    thread = new Thread(club.threadGroup, this, "SponsorCanvas");
    thread.start();		// will cause this.run() method to be invoked
  }

  private void setup() {
    gifs = new Vector(20,20);	// String name of GIF files
    imgs = new Vector(20,20);	// Image of GIFs
    urls = new Vector(20,20);	// URL of target click throughs

    // Hardcode initial WXL banner in case PROGRAM.txt error:
    String adGIF = "wxl"+ADW+"x"+ADH+".gif";
    gifs.addElement(adGIF);
    imgs.addElement(ImageButton.load(adGIF,this,false));
    urls.addElement(Club.newURL(Login.serverWeb));

    // Now load the local banner program file:
    try {
      URL url = new URL(Login.serverLocal+"/banners/PROGRAM.txt");
      DataInputStream in = new DataInputStream(url.openStream());
      String line;
      StringTokenizer st;
      while ((line=in.readLine())!=null) {
	st = new StringTokenizer(line," \t");
	if (st.countTokens()<2)
	  continue;
	adGIF = st.nextToken(); // filename of ad gif banner
	if (adGIF.startsWith("#")) // comment line
	  continue;
	String adTarget = st.nextToken(); // URL of click through target
	gifs.addElement(adGIF);
	// imgs will be loaded only on demand
	urls.addElement(Club.newURL(adTarget));
	//Club.debug("SponsorCanvas.setup: "+adGIF+" "+adTarget);
      }
      in.close();
    } catch (Exception e) {
      Club.warning(e,"SponsorCanvas.setup error: "+e);
    }
  }
  
  private static long stamp = 0;
  /** Return ms since last stamp, also update the stamp now. */ 
  private static synchronized long stamp() {
    long t = System.currentTimeMillis(); // time now (in ms)
    long delta = t - stamp;	// ms since last stamp
    stamp = t;			// update to now
    return delta;
  }
  
  public void run() {
    int min=0;
    while (thread!=null) {
      long ms = ADSEC*1000;
      stamp();
      while (ms>1000) {
	try { thread.sleep(ms); }
	catch (InterruptedException e) {}
	if ((++min % 3)==0) {
	  min = 0;
	  //club.send("log sponsor "+clicked+"/"+viewed);
	}
	ms -= stamp();
      }
      nextBanner(false);
    }
  }

  public boolean mouseEnter(Event event, int x, int y) {
    club.cursor("SponsorCanvas",Frame.HAND_CURSOR);
    return true;
  }
  public boolean mouseExit(Event event, int x, int y) {
    club.cursorReset("SponsorCanvas");
    return true;
  }
  

  public boolean handleEvent(Event event) {
    //Club.debugEvent("SponsorCanvas",event);
    if (event.id==Event.KEY_ACTION || event.id==Event.KEY_PRESS)
      return club.handleKey(event);
    if (event.id==Event.MOUSE_DOWN) // no Canvas.mouseDown() in JDK 1.0
      return click();
    return super.handleEvent(event);
  }

  // -----------------------------------------------------------------
  public void debug(String message) {
    //Club.debug("SponsorCanvas."+message+" "+
    //desired+" of "+displayed+"/"+loaded+", "+gifs.size());
  }
  
  public boolean click() {
    clicked++;
    Club.debug("SponsorCanvas click "+clicked+
	       " (" + (100*clicked)/viewed + "% of "+viewed+")");
    URL url = (URL)urls.elementAt(displayed);
    if (url==null)
      return true;		// click null banner!
    club.state(url.toString());
    System.out.println("open "+url.toString());
    // BUG: sometimes stops working on some browsers, e.g,. N3!!
    // _self current frame, _parent parent, _top top, _blank new
    Login.appletContext.showDocument(url,url.toString());
    return true;
  }

  public boolean prev() {	// Club.sponsorPanel prev button
    debug("prev");
    if (desired!=displayed) {
      club.state("Loading "+(String)gifs.elementAt(desired));
      return true;		// still waiting for prev load
    }
    desired = displayed-1;
    if (desired<1)
      desired=loaded;		// cycle back to last banner loaded
    repaint();
    return true;
  }
  public boolean next() {	// Club.sponsorPanel next button
    debug("next");
    if (desired!=displayed) {
      club.state("Loading "+(String)gifs.elementAt(desired));      
      return true;		// next waiting for load
    }
    stamp();
    nextBanner(true);		// will load next from cache
    return true;
  }

  /** Display next banner, load from net or cache.
   * Called by timer thread (new banner every 60 seconds)
   *  and on Club sponsorPanel next ImageButton mouse click event.
   */
  public synchronized boolean nextBanner(boolean user) {
    debug("nextBanner");
    desired++;
    if (desired>loaded) {
      if (desired>=gifs.size()) {
	debug("nextBanner reset");
	desired = 1;		// cycle back to first banner now
      } else {
	String adGIF = (String)gifs.elementAt(desired);
	//Club.debug("SponsorCanvas load "+adGIF);
	Image image = ImageButton.load(Login.serverLocal+"/banners/"+adGIF,
				       this,true); // waits until loaded
	imgs.addElement(image);
	displayed = loaded = desired;
      }
    }
    repaint();
    viewed++;			// don't count prev review
    return true;
  }

  // -----------------------------------------------------------------
  public void update(Graphics g) { paint(g); }
  public void paint(Graphics g) {
    // BUG. ArrayIndexOutOfBoundsException (karl 25mar98)
    // 8>=8
    if (desired==imgs.size()) {
      Club.debug("SponsorCanvas.paint "+
		 desired+" of "+displayed+"/"+loaded+", "+imgs.size());
      --desired;
    }
    Image image = (Image)imgs.elementAt(desired);
    int width = image.getWidth(this);
    if ( width>0 ) {
      displayed = desired; // success
    } else {
      image = (Image)imgs.elementAt(displayed);
      width = image.getWidth(null);
    }
    int height = image.getHeight(null);

    g.setColor(getBackground());
    g.fillRect(0,0,ADW,ADH+2);

    // Sample banner sizes:
    // - LinkExchange 440x40, left 40 bits are annoying LE logo.
    // - WebUnion 400x40, and Yahoo 468x60
    // - adcouncil.org/banner/ 468x60, 392x72, 200x80
    g.drawImage(image,(ADW-width)/2,(ADH-height)/2,this);
  }
  //Netscape 4 on Win95 flashes the banners
  //about once per second. Notes from dejanews about resource:
  //1.Call image.flush() on the animated gif's Image instance.
  //2.Modify the imageUpdate method of the ImageObserver that
  //you use so that when you are done with it it notifies
  //the image producer that it does not require any more updates.
}
