var imageslideshowEngine = function() {
    /*
    author:Giuseppe
    date: 20/08/2007
    notes:
    This function is to fade in and out the images and linkboxes.
	 
	 Revised and modified by Matt for Roccoforte Angleterre adding JQuery functionality, pause, play and image jump
    Revised by Giuseppe 17/09/2008 fixed minor naming problem
    Revised by Matt 19/09/2008
    - corrected the year in Giuseppe's previous revision date ;)
    - added optional this.fadeSpeed, and made interval optional as well
    - added optional callback parameter, which should be a function expecting a single object:
    - { from: i, to: j },  where i and j are the image indices
	 
	 NOTE: Requires JQuery
    */
    this.name = 'imageslideshowEngine';
    this.currentIndex = 0;
    //initializing to [] so later on the a.length function will not fail if either the images or linkboxes are not available
    this.images = [];
    this.linkboxes = [];
    this.pairs = [];
    this.fadeClock = null;
    this.linkboxMaxHeight = 0;

    this.init = function(interval, fadeSpeed, callback) {
        var i;
        this.interval = interval ? interval : 3000;
        this.fadeSpeed = fadeSpeed ? fadeSpeed : 1000;
        this.callback = callback;

        for (i = 1; i < this.images.length; i++) {
            this.initElement(this.images[i]);
        }
        for (i = 1; i < this.linkboxes.length; i++) {
            this.initElement(this.linkboxes[i]);
        }
        this.associateImagesToLinkboxes();
        this.currentIndex = 0;
        var slideshowengine = this;
        this.fadeClock = setInterval(function() {
            slideshowengine.fadeEngine();
        }, this.interval);
    };

    this.doFade = function(fromIndex, toIndex) {

        if (this.pairs === undefined || this.pairs.length <= 1) {
            return;
        }
        
        var pairout = this.pairs[fromIndex];
        var pairin = this.pairs[toIndex];

        

        // only fade out if we're actually swapping to a new item
        if (pairout.image != pairin.image) {
            this.fadeOut(pairout.image);
        }
        if (pairout.linkbox != pairin.linkbox) {
            this.fadeOut(pairout.linkbox);
        }

        this.fadeIn(pairin.image);
        this.fadeIn(pairin.linkbox);

        if (this.callback) {
            this.callback({
                from: fromIndex,
                to: toIndex
            });
        }

        this.currentIndex = toIndex;

    };

    this.fadeEngine = function() {
        var outIndex = this.currentIndex;
        var inIndex = (this.currentIndex === undefined) ? 0 : (++(this.currentIndex) >= this.pairs.length) ? 0 : this.currentIndex;

        this.doFade(outIndex, inIndex);
    };


    this.jumpToPair = function(toIndex, pause) {
        if (pause) {
            this.pauseEngine();
        }
        this.doFade(this.currentIndex, toIndex);
    };

    this.pauseEngine = function() {
        clearInterval(this.fadeClock);
    };

    this.unpauseEngine = function() {
        var slideshowengine = this;
        this.fadeClock = setInterval(function() {
            slideshowengine.fadeEngine();
        }, this.interval);
    };

    this.getLinkboxMaxHeight = function() {
        for (var i = 0; i < this.linkboxes.length; i++) {
            this.linkboxMaxHeight = Math.max(this.linkboxMaxHeight, this.linkboxes[i].offsetHeight);
        }
        return this.linkboxMaxHeight;
    };

    this.associateImagesToLinkboxes = function() {
        var maxindex = this.images.length > this.linkboxes.length ? this.images.length : this.linkboxes.length;

        for (var i = 0; i < maxindex; i++) {
            var o = {};
            o.image = (this.images[i]) ? this.images[i] : this.images.length > 0 ? this.images[this.images.length - 1] : null;
            o.linkbox = (this.linkboxes[i]) ? this.linkboxes[i] : this.linkboxes.length > 0 ? this.linkboxes[this.linkboxes.length - 1] : null;
            this.pairs.push(o);
        }
    };

    this.initElement = function(el) {
        jQuery(el).hide();
    };

    this.fadeIn = function(el) {
        jQuery(el).fadeIn(this.fadeSpeed);
    };

    this.fadeOut = function(el) {
        jQuery(el).fadeOut(this.fadeSpeed);
    };
};
