/*
 * Image Carousel v1.0 - Jordy Boezaard - http://www.bitterzoetmedia.nl/
 *
 * TERMS OF USE
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2011 Jordy Boezaard
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/
function SlideData()
{
    this.link = null;
    this.imageUrl = null;
    this.imageLoaded = false;
}


function ImageCarousel () {
    this.fadeInDuration = 1500;
    this.fadeOutDuration = 1500;
    this.sleepDuration = 5000;
    this.retryTimeoutDuration = 100;
    this.currentPos = 0;
    this.lastAnimationStartTime = null;
    this.slideData = null;
    this.isFirst = true;
};

ImageCarousel.prototype.Init = function ()
{
    // Get elements    
    var listChildren = $('ul#imageCarousel').children();
    
    var slideDataArray = new Array();

    $.each(listChildren, function()
    {
        if (this.tagName.toLowerCase() == 'li')
        {
            var slideData = new SlideData();
            
            slideData.link = $(this).find('a').attr('href');
            slideData.imageUrl = $(this).find('img').attr('src');
            
            slideDataArray.push(slideData);
        }
    }); 
    
    this.slideData = slideDataArray;
    
    if (this.slideData.length == 0)
    {
        return;
    }
    
    // Replace list for div
    var divContainer = $('<div/>', {
        id:    'imageCarousel'
    }).append($('<a/>').append('<img/>'));
    
    $('ul#imageCarousel').replaceWith(divContainer);

    
    // Fade elements out
    $('div#imageCarousel').fadeOut(0);
    
    // Preload images
    this.PreloadImages();

    // Start fadein/out sequence
    this.Animate();
}

ImageCarousel.prototype.PreloadImages = function ()
{    
    var onloadFunction = function ()
    {
        this.slideData.imageLoaded = true;
    }
        
    jQuery.each(this.slideData, function ()
    {
        var pic = new Image();
        pic.slideData = this;
        pic.onload = onloadFunction;
        pic.src = this.imageUrl;
    });
}

ImageCarousel.prototype.FadeOut = function ()
{
    // Create callback
    var selfObj = this;
    var callBack = function(){
        selfObj.FadeIn();
    };
    
    // Fade-out current image
    $('div#imageCarousel').fadeOut(this.fadeOutDuration, callBack);
}

ImageCarousel.prototype.FadeIn = function ()
{
    // Create callback
    var selfObj = this;
    var callBack = function(){
        selfObj.Animate();
    };
    
    // Fade-in next image
    $('div#imageCarousel').find('a').attr('href', this.slideData[this.currentPos].link);
    $('div#imageCarousel').find('img').attr('src', this.slideData[this.currentPos].imageUrl);
    $('div#imageCarousel').fadeIn(this.fadeInDuration, callBack);
    
    // Set current position to next index
    this.currentPos++;
    
    if (this.currentPos >= this.slideData.length)
    {
        this.currentPos = 0;
    }
}

ImageCarousel.prototype.Animate = function (selfObj)
{
    if (selfObj == undefined)
    {
        selfObj = this;
    }
    
    if (selfObj.lastAnimationStartTime == null)
    {
        selfObj.lastAnimationStartTime = new Date().getTime();
    }

    if (selfObj.slideData[selfObj.currentPos].imageLoaded == false)
    {
        // Wait until image is preloaded
        var callBackAnimate = function(){
            selfObj.Animate(selfObj);
        };
                
        setTimeout(callBackAnimate, selfObj.retryTimeoutDuration);
        
        return;
    }

    // Calculate passed time
    var timeTaken = new Date().getTime() - selfObj.lastAnimationStartTime;

    // Reset animation start time
    selfObj.lastAnimationStartTime = null;
    
    // Check if it's the first image
    if (selfObj.isFirst == true)
    {
        selfObj.isFirst = false;
        selfObj.FadeIn();
    }
    else
    {
        // Loading took at least as long as sleep duration?
        if (timeTaken >= selfObj.sleepDuration)
        {
            // Go to next image
            selfObj.FadeOut();
        }
        else
        {
            // Wait for remaining time
                
            // Create callback fade out
            var callBackFadeOut = function(){
                selfObj.FadeOut();
            };
            
            setTimeout(callBackFadeOut, selfObj.sleepDuration - timeTaken);
        }
    }
}
