/*
 * The 'global' array of images to fade
 */
var images = new Array();

/*
 * The index of the current image in the images array
 */
var index = 0;

/**
 * Initialises the array of image elements to fade/blend
 *
 * @param id The ID of the element containing the images
 */
function initImages(id) {

    var el = document.getElementById(id);    
    if (el) {
        images = el.getElementsByTagName('IMG');        
    }
}

/**
 * Get the index relating to the image a given position from
 * the currently 'active' index in the images array
 */
function getIndex(i) {
    
    // See how many past the end we are
    var diff = (images.length - 1) - (index + i);
    // alert((index + 1) + ' : ' + diff);
    
    if (diff >= 0) {
        return (index + i);
    } else {
        return (Math.abs(diff) - 1);
    }
}

/**
 * Initialises the blending of images
 *
 * @param id The ID of the element that contains the images
 * to blend
 * @param blendTime The number of milliseconds the actual
 * blending from one image to another should take
 * @param pauseTime The number of milliseconds to wait once the
 * blend has finished before the image should blend to the
 * next one
 * @param quality [optional] The quality of the transition when
 * blending from one image to the next
 *   100:    the new object fades in at every opacity level
 *   0 or 1: the object changes in a single step
 */
function initBlending(id, blendTime, pauseTime, quality) {

    // Set the images
    initImages(id);

    // Only do the blending if there's more than one image
    if (images.length > 1) {
        
        // Explicitly set the first image's opacity (this is required so
        // the getOpacity function returns a valid value for this element)
        setOpacity(0, 100);
        
        // Set each of the images other than the first to invisible using their
        // opacity (i.e. make them clear) but then make them visible style-wise
        for (var i=1; i<images.length; i++) {
            setOpacity(i, 0);
            images[i].style.display = 'block';
        }

        // Make sure there is a valid pause time between blends
        if (pauseTime < 0) pauseTime = 0;

        // Start the blending on a repeat loop
        setInterval('doBlend(' + blendTime + ',' +  quality + ')', blendTime + pauseTime);
    
        // Do the first blend now so we don't have to wait for the full total
        // time without any blending
        doBlend(blendTime, quality); // starts too quickly
    
    }

}

/**
 * Blends the next image in hiding the current one
 *
 * @param blendTime The number of milliseconds it takes to fade the new
 * image in
 * @param quality The quality % dictating how frequently the image should
 * be refreshed while fading in
 */
function doBlend(blendTime, quality)
{
    // Get the index for the next image
    var nextIndex = getIndex(1);
        
    // Bring the next image to the front
//    images[index].style.zIndex = 2;
//    images[nextIndex].style.zIndex = 3;
    
    // Fade in the next image and out the current image
    blendToOpacity(nextIndex, 100, blendTime, quality);
    blendToOpacity(index, 0, blendTime, quality);
    
    // Hide the old image
    // setOpacity(currImg, 0);
//    setTimeout('setOpacity(' + index + ',0)', blendTime);
    
    // Increment the images array index
    index = nextIndex;
}

/**
 * Blends the given object to the specified
 * opacity over the given time period
 *
 * @param i The index of the object to blend in the images array
 * @param newOpacity The opacity value to end up at
 * @param millisecs The number of milli seconds for
 * the blend transition to take
 * @param quality [optional] The quality % of the blend
 *   100:    the object is displayed at every opacity level
 *   0 or 1: the object changes to the new opacity level in a
 *           single step
 */
function blendToOpacity(i, newOpacity, millisecs, quality) {

    // Ensure the quality is a valid value
    if (quality == null) quality = 80;
    if (quality < 1) quality = 1;
    if (quality > 100) quality = 100;

    // Get the object's current opacity
    var currOpacity = getOpacity(images[i]);
    
    // Set the opacity and time steps
    var opacityStep = (newOpacity-currOpacity)/quality;
    var timeStep = Math.round(millisecs/quality);
    
    // Ensure the step vars are valid
    if (timeStep < 1) timeStep = 1;
        
    // Only bother if there's a change in opacity required
    if (Math.abs(opacityStep) > 0.9) {
    
        // Change the opacity
        for (var j=1; j<=quality; j++) {
            setTimeout('setOpacity(' + i + ',' + (currOpacity + (j*opacityStep)) + ')', (j*timeStep));
        }
    }
}

/**
 * Sets the opacity of an object. Allows for different
 * browsers handling of opacity
 *
 * @param i The index of the object in the images array to set
 * the opacity on
 * @param opacity The opacity % value to set
 */
function setOpacity(i, opacity) {

    opacity = Math.round(opacity);
    
    // Make sure the opacity is a valid value
    if (opacity < 0) opacity = 0;
    if (opacity > 100) opacity = 100;
    
    var objStyle = images[i].style;
    
    // Set the opacity for the various browser types
    objStyle.opacity = (opacity / 100);
    objStyle.MozOpacity = (opacity / 100);
    objStyle.KhtmlOpacity = (opacity / 100);
    objStyle.filter = 'alpha(opacity=' + opacity + ')';
}

/**
 * Gets the opacity of an object. Allows for different
 * browsers handling of opacity
 *
 * @param obj The object to get the opacity for
 */
function getOpacity(obj) {
    
    var objStyle = obj.style;
    
    // Set the opacity for the various browser types
    var opacity = objStyle.opacity;

    if (!opacity) opacity = objStyle.MozOpacity;
    if (!opacity) opacity = objStyle.KhtmlOpacity;
    
    // MSIE
    if (!opacity) {
        var str = objStyle.filter;
        var i = str.indexOf('opacity=');
        if (i > -1) {
            opacity = '' + parseInt(str.substring(i + 'opacity='.length));
        }
    }
    
    // Default if still not set
    if (!opacity) opacity = 1;
 
    return Math.round(opacity * 100);
}
