/*
 * version 1.0.4
 * Copyright 2004-2005, Peter Rowntree. All Rights Reserved.
 * http://www.hdyn.com/wr/common/contact.php?addr=pr
 */

SlideSet.prototype.getNSlides=getNSlides;
SlideSet.prototype.startTimer=startTimer;
SlideSet.prototype.stopTimer=stopTimer;
SlideSet.prototype.rtg=rtg;
SlideSet.prototype.timerDone=timerDone;
SlideSet.prototype.loadDone=loadDone;
SlideSet.prototype.display=display;
SlideSet.prototype.setTemp=setTemp;
SlideSet.prototype.set=set;
SlideSet.prototype.reset=reset;
SlideSet.prototype.next=next;
SlideSet.prototype.prev=prev;
SlideSet.prototype.start=start;
SlideSet.prototype.stop=stop;
SlideSet.prototype.reverse=reverse;
SlideSet.prototype.setVisible=setVisible;
SlideSet.prototype.changeTemp=changeTemp;
SlideSet.prototype.setTimerMinMax=setTimerMinMax;

var g_trans=new Image();
g_trans.src="images/trans.gif";
var g_timerRetryMS=1000;

var g_slideSets=new Array();

function setSlideSet(i,arr)
{
   g_slideSets[i]=new SlideSet(i,arr);
}

//can take 3rd, 4th & 5th args: destOb,min,max; destOb may be null, img object, or string id;
//see constructor for defaults
function setSlideSetPrefs(i,flags)
{
   if(i >= g_slideSets.length)
      return null;
   var ss=g_slideSets[i];
   var destOb=(arguments.length > 2) ? arguments[2] : null;
   if(typeof destOb == 'string')
      destOb=document.getElementById(destOb);
   else
      destOb=destOb;
   ss.flags=flags;
   ss.destOb=destOb;
   var min=-1,max=-1;
   if(arguments.length > 3)
      min=arguments[3];
   if(arguments.length > 4)
      max=arguments[4];
   ss.setTimerMinMax(min,max);
   return ss;
}

function willPin(i,nSlides,flags)
{
   if(!(flags & 1))
      return false;
   if(flags & 8)   //bkwds
   {
      if(i <= 0)
         return true;
   }
   else
   {
      if(i >= nSlides-1)
         return true;
   }
   return false;
}

function getNextTempIndex(ob)
{
   var nSlides=ob.getNSlides();
   if(nSlides < 1)
      return -100;
   var i=ob.current;
   if(ob.flags & 4)
   {
      i=Math.floor(Math.random()*(nSlides-0.5))+1; //always <= nSlides
      if(i == ob.current)
         ++i;
   }
   else if(ob.flags & 8)
      --i;
   else
      ++i;
   return constrainTempIndex(i,nSlides,ob.flags & 1);
}

//pin => no rotate
function constrainTempIndex(i,nSlides,pin)
{
   while(i >= nSlides)
      i=pin ? nSlides-1 : i-nSlides;
   while(i < 0)
      i=pin ? 0 : nSlides+i;
   return i;
}

function constrainObTempIndex(i,ob)
{
   var nSlides=ob.getNSlides();
   if(nSlides < 1)
      return -100;
   return constrainTempIndex(i,nSlides,ob.flags & 1);
}

//-------------SlideSet object--------------------

//flags:
//1 => pin to ends (no rotate)
//2 => loading img
//4 => random image
//8 => go backwards
//16 => timer enabled
//32 => visible
function SlideSet(i,arr)
{
   this.i=i;
   this.arr=arr;
   this.flags=16; //timer only
   this.current=-1;
   this.timer=null;
   this.tempImg=document.createElement('img');
   this.tempImg.ownerSet=this;
   this.tempImg.onload=imgLoadDone;
   this.destOb=null;
   this.timerMin=5000;  //ms.
   this.timerMax=10000;
   this.displaySrc=g_trans.src;
}

//param < 0 => no change
//max > min => random interval in range
//max == min => fixed interval
function setTimerMinMax(min,max)
{
   if(min >= 0 && min < 10)
      min=10;
   if(max >= 0 && max < min)
      max=min;
   if(min >= 0)
      this.timerMin=min;
   if(max >= 0)
      this.timerMax=max;
}

function getNSlides()
{
   if(this.arr == null)
      return 0;
   return this.arr.length;
}

function startTimer()
{
   this.stopTimer();   //be safe
   if((this.flags & 48) == 48)   //timing & visible
   {
      var t;
      if(this.timerMax == this.timerMin)
         t=this.timerMin;
      else
         t=Math.floor(Math.random()*(this.timerMax-this.timerMin))+this.timerMin;
      this.timer=setTimeout("g_slideSets["+this.i+"].timerDone()",t);
   }
}

function stopTimer()
{
   if(this.timer != null)
   {
      clearTimeout(this.timer);
      this.timer=null;
   }
}

//restart-transfer-get
function rtg()
{
   this.stopTimer();   //be safe
   if(willPin(this.current,this.getNSlides(),this.flags))
   {
      this.display(this.tempImg.src);
      return;
   }
   this.startTimer();
   this.display(this.tempImg.src);
   this.changeTemp(-100);
}

//----------------
//if threads can only yield on JS statement boundaries,
//the following are thread-safe; if not, a race condition
//(probably very rare) could stop the timer.
function timerDone()
{
   this.stopTimer();
   if((this.flags & 2) == 0)  //not loading
      this.rtg();
}

var g_e=null;
function loadDone()
{
   this.flags &= ~2;
   if(this.timer == null && (this.flags & 48) == 48) //timing & visible, and timer done
      this.rtg();
}
//----------------

function imgLoadDone(e)
{
   if(typeof this.ownerSet == 'undefined')
      return false;
   this.ownerSet.loadDone();
   return true;
}

//src == null => blank dest, but leave this.displaySrc untouched
function display(src)
{
   if(src == null)
      src=g_trans.src;
   else
      this.displaySrc=src;
   if(this.destOb == null)
      document.body.background=src;
   else
      this.destOb.src=src;
}

function setTemp()
{
   var path=(this.arr == null ? g_trans.src : this.arr[this.current]);
   this.flags |= 2;  //loading
   this.tempImg.src=path;
}

function next()
{
   if(this.flags & 8)
      this.reverse();
   this.rtg();
}

function prev()
{
   if(!(this.flags & 8))
      this.reverse();
   this.rtg();
}

function start()
{
   this.flags |= 16;
   this.startTimer();
}

function stop()
{
   this.flags &= ~16;
   this.stopTimer();
}

function reverse()
{
   this.flags ^= 8;
   if(this.current >= 0) //always, after start
   {
      var delta=((this.flags & 8) ? -2 : 2);
      this.changeTemp(this.current+delta);
   }
}

function set()
{
   this.stopTimer();
   this.display(this.displaySrc);  //show current
   if(!(this.flags & 2))  //if timer is on, loadDone will call rtg
      this.startTimer();
}

function reset()
{
   this.stopTimer();
   var i=(this.flags & 8) ? this.getNSlides()-1 : 0;
   this.display(this.arr[i]);
   this.changeTemp(i);
   if((this.flags & 48) == 48)   //timing & visible
      ;  //loadDone will call rtg
   else
      this.rtg();
}

function setVisible(vis)
{
   if(vis)
   {
      this.flags |= 32;
      if(this.current < 0)
         this.reset();
      else
         this.set();
   }
   else
   {
      this.flags &= ~32;
      this.stopTimer();
      this.display(null);
   }
}

//i == -100 => next
function changeTemp(i)
{
   if(i == -100)
      i=getNextTempIndex(this);
   else
      i=constrainObTempIndex(i,this);
   if(i >= 0)
   {
      this.current=i;
      this.setTemp();
   }
}

//---------end SlideSet object--------------------