/**
 * Sets the opacity of the object in the current context.
 *
 * @param integer opacity
 * @return void
 */
jQuery.fn.setOpacity = function(opacity)
{
    if ($.browser.msie) {
        this.attr("style", "filter: alpha(opacity=" + opacity*100 + ");");
    } else {
        this.attr("style", "opacity: " + opacity + ";");
    }
}

/**
 * Returns the current timestamp in milliseconds
 *
 * @return integer
 */
function getTime()
{
    return (new Date()).getTime();
}

/**
 * Class that handles the fading between various images
 */
function NovaraFader(imgSet1, imgSet2, fadeTo)
{
    /**
     * The time that the fader is started.  Used for determining when to fade
     * in/out.
     *
     * @var integer
     */
    var _startTime = getTime();

    /**
     * The first image set used in fading.
     *
     * @var object
     */
    var _imgSet1 = imgSet1;

    /**
     * The second image set used in fading.  This image starts off faded out
     *
     * @var object
     */
    var _imgSet2 = imgSet2;

    /**
     * How much to fade out to (0 is completely, 1 is never fade out)
     *
     * @var float
     */
    var _fadeTo = fadeTo;

    /**
     * How long fades should last (in ms)
     *
     * @var integer
     */
    var _fadeDuration = 2000;

    /**
     * How long a fade cycle (fading + standing still) should last.  Should be
     * bigger than _fadeDuration
     *
     * @var integer
     */
    var _fadeCycle = 5000;

    /**
     * The direction to fade (imgset1->imgset2 vs.  * imgset2->imgset1).  1 if
     * forward, 0 if reverse.
     *
     * @var integer
     */
    var _direction = 1;

    /**
     * How frequently (in ms) to update opacities when fading.
     *
     * @var integer
     */
    var _timerInterval = 50;

    /**
     * The ID of the interval
     *
     * @var string
     */
    var _interval;

    __construct();

    /**
     * Constructor - sets the initial opacities.
     *
     * @return void
     */
    function __construct()
    {
        _imgSet2.setOpacity(_fadeTo);
    }

    /**
     * Starts the fading action.
     *
     * @return void
     */
    this.run = function()
    {
        _run();
    }

    /**
     * Starts the fading action.
     *
     * @return void
     */
    function _run()
    {
        var timeout = _getNextTimeout();
        setTimeout(_startFade, timeout);
    }

    /**
     * Determines the next time that something needs to happen.
     *
     * @return integer
     */
    function _getNextTimeout()
    {
        var cyclePosition = (getTime() - _startTime) % _fadeCycle;
        var nextTimeout = _fadeCycle - _fadeDuration - cyclePosition;
        if (nextTimeout < 0) {
            nextTimeout = 0;
        }
        return nextTimeout;
    }

    /**
     * See how far the images need to be faded out.
     *
     * @return float  number between 0 and 1
     */
    function _getFadeLevel()
    {
        var cyclePosition = (getTime() - _startTime) % _fadeCycle;
        /*
        if (cyclePosition < _fadeCycle - _fadeDuration) {
            // We should be done
            if (_direction == 1) {
                return 1;
            } else {
                return 0;
            }
        }
        */
        var fadePosition = cyclePosition - _fadeCycle + _fadeDuration;
        var fadeLevel = fadePosition / _fadeDuration;
        if (fadeLevel < 0 || fadeLevel > 1) {
            // We should be done fading
            fadeLevel = 1;
        }
        return fadeLevel;
    }

    /**
     * Starts the fading action
     *
     * @return void
     */
    function _startFade()
    {
        _interval = setInterval(_doFade, _timerInterval);
    }

    /**
     * Slightly fades out the images
     *
     * @return void
     */
    function _doFade()
    {
        var fadeLevel = _getFadeLevel();

        var fadePosition;
        if (_direction == 1) {
            fadePosition = fadeLevel;
        } else {
            fadePosition = 1 - fadeLevel;
        }

        var opacityRange = 1 - _fadeTo;
        _imgSet1.setOpacity(1 - opacityRange*fadePosition);
        _imgSet2.setOpacity(_fadeTo + opacityRange*fadePosition);

        if (fadeLevel == 1) {
            // We're done
            clearInterval(_interval);
            // Reverse direction
            _direction *= -1;
            _run();
        }
    }
}

$(function() {
    var fader = new NovaraFader($(".slideshow_imgset1"), $(".slideshow_imgset2"), .2);
    fader.run();
});
