/*
*	Name:			jquery.ryslider.2.js
    Purpose:        Rebuild of the old version. This one features proper constructors, destructors
*/

(function ($) {
    jQuery.fn.ryslider = function (options, i) {
        if (this.length > 1) {
            var a = new Array();
            this.each(
                function (i) {
                    a.push($(this).ryslider(options, i));
                });
            return a;
        }
        var opts = $.extend({}, $().ryslider.defaults, options), slideWidth, slideHeight, slideCount, pageCount, playInterval, playState, currentPage;

        // Public functions

        this.Destroy = function (reInit) {
            var container = this, $wrapper = $(container).parent(), reInit = (reInit != undefined) ? reInit : false;
            if (opts.beforeDestroyFunction != null && $.isFunction(opts.beforeDestroyFunction))
                opts.beforeDestroyFunction($(container), opts, reInit);
            $(container).stop();
            $(container).children().stop();
            if (opts.stateSelector == null)
                $wrapper.children('.' + opts.stateContainerClass).remove();
            else
                $(opts.stateSelector).children('.' + opts.stateContainerClass).remove();

            if (opts.pageSelector == null)
                $wrapper.children('.' + opts.pageContainerClass).remove();
            else
                $(opts.pageSelector).children('.' + opts.pageContainerClass).remove();

            if (opts.nextSelector == null)
                $wrapper.children('.' + opts.nextButtonClass).remove();
            else
                $(opts.nextSelector).unbind('click.rySlider.onNextClick').removeClass(opts.enabledClass + ' ' + opts.nextButtonClass);
            if (opts.prevSelector == null)
                $wrapper.children('.' + opts.prevButtonClass).remove();
            else
                $(opts.prevSelector).unbind('click.rySlider.onPrevClick').removeClass(opts.enabledClass + ' ' + opts.prevButtonClass);

            if (opts.playSelector == null)
                $wrapper.children('.' + opts.playButtonClass).remove();
            else
                $(opts.playSelector).unbind('click.rySlider.onPlayClick').removeClass(opts.enabledClass + ' ' + opts.playButtonClass);

            if (opts.stopSelector == null)
                $wrapper.children('.' + opts.stopButtonClass).remove();
            else
                $(opts.stopSelector).unbind('click.rySlider.onStopClick').removeClass(opts.enabledClass + ' ' + opts.stopButtonClass);

            $(container).children(opts.contentElement).each(function (index) {
                $(this).removeAttr('style').removeClass('slide-' + (index + 1) + ' ' + opts.contentClass + ' ' + opts.enabledClass);
            });
            slideWidth = null; slideHeight = null; slideCount = null; pageCount = null; playInterval = null; playState = null, currentPage = null;

            $(container).removeData('rySlider').removeAttr('style').removeClass(opts.containerClass).unwrap();
            if (opts.afterDestroyFunction != null && $.isFunction(opts.afterDestroyFunction))
                opts.afterDestroyFunction($(container), opts, reInit);
        }; // end destroy function

        this.Update = function (options) {
            opts = null;
            opts = $.extend({}, $().ryslider.defaults, options);
            this.Destroy(true);
            return this.Create();
        }

        this.Create = function (iteration) {
            var container = this;

            if ($(container).data('rySlider') == true)
                return this;
            if (opts.beforeCreateFunction != null && $.isFunction(opts.beforeCreateFunction))
                opts.beforeCreateFunction($(container), opts);

            $(container).data('rySlider', true);

            var totalWidth = 0, $wrapper = $(container).wrap('<div class="' + opts.wrapperClass + '" />').parent();
            $(container).addClass(opts.containerClass);

            slideHeight = $(container).outerHeight(false);
            slideCount = $(container).children(opts.contentElement).size();

            // add blank children as required for paging
            var initialSlideCount = $(container).children(opts.contentElement).size(), emptySlotString = '', startpage = 1, actualSlideWidth = null;
            if (initialSlideCount % opts.itemsToDisplay != 0) {
                for (i = 1; i <= opts.itemsToDisplay - (initialSlideCount % opts.itemsToDisplay); i = i + 1) {
                    emptySlotString += '<' + opts.contentElement + '></' + opts.contentElement + '>';
                }
                $(container).append(emptySlotString);
            }

            slideCount = $(container).children(opts.contentElement).size();
            pageCount = slideCount / opts.itemsToDisplay;

            // catch stupidity
            if (opts.startItem <= 0 || opts.itemsToDisplay > opts.startItem)
                startpage = 1;
            else if (opts.startItem >= slideCount)
                startpage = pageCount;
            else {
                var remainder = opts.startItem % opts.itemsToDisplay;
                var startpage = (opts.startItem - remainder) / opts.itemsToDisplay;
                if (remainder != 0)
                    startpage += 1;
            }

            // set heights etc of container
            $(container).children(opts.contentElement).each(function (index) {
                var $slide = $(this);
                $slide.addClass('slide-' + (index + 1) + ' ' + opts.contentClass);
                if (slideWidth == null)
                    slideWidth = $slide.width();
                if (actualSlideWidth == null)
                    actualSlideWidth = $slide.width() - (parseInt($slide.css('margin-left')) + parseInt($slide.css('margin-right')));
                $slide.css({ left: (index * $slide.width()) + parseInt($slide.css('margin-left'))
                });

                if (index + 1 < opts.startItem + opts.itemsToDisplay &&
                    index + 1 >= opts.startItem) {
                    $slide.addClass(opts.enabledClass);
                }
                totalWidth += $slide.outerWidth();
            });

            $(container).css({ left: 0, width: (actualSlideWidth * slideCount) * 2 });
            currentPage = 1;

            if (startpage > 1) {
                var tmpSpeed = opts.speed;
                opts.speed = 0;
                gotoPage(container, startpage, opts.autoPlay);
                opts.speed = tmpSpeed;
            }

            // create paging buttons and pager links
            if (slideCount > opts.itemsToDisplay) {
                if (opts.renderNext) {
                    if (opts.nextSelector == null)
                        $('<a href="#" class="' + opts.nextButtonClass + '">Next</a>').appendTo($wrapper).bind('click.rySlider.onNextClick', function () { nextSlide(container, opts.itemsToDisplay, true); return false; });
                    else
                        $(opts.nextSelector).addClass(opts.nextButtonClass).bind('click.rySlider.onNextClick', function () { nextSlide(container, opts.itemsToDisplay, true); return false; });
                }
                if (opts.renderPrevious) {
                    if (opts.prevSelector == null)
                        $('<a href="#" class="' + opts.prevButtonClass + '">Previous</a>').appendTo($wrapper).bind('click.rySlider.onPrevClick', function () { previousSlide(container, opts.itemsToDisplay, true); return false; });
                    else
                        $(opts.prevSelector).addClass(opts.prevButtonClass).bind('click.rySlider.onPrevClick', function () { previousSlide(container, opts.itemsToDisplay, true); return false; });
                }
                if (opts.enablePlayStop) {
                    // Play Button
                    var play, stop;
                    if (opts.renderPlayButton) {
                        if (opts.playSelector == null)
                            play = $('<a href="#">Play</a>').appendTo($wrapper).addClass(opts.playButtonClass).bind('click.rySlider.onPlayClick', function () { playSlider(container); return false; });
                        else
                            play = $(opts.playSelector).addClass(opts.playButtonClass).bind('click.rySlider.onPlayClick', function () { playSlider(container); return false; });

                        if (opts.autoPlay)
                            play.addClass(opts.enabledClass);
                    }

                    // Stop Button
                    if (opts.renderStopButton) {
                        if (opts.stopSelector == null)
                            stop = $('<a href="#">Stop</a>').appendTo($wrapper).addClass(opts.stopButtonClass).bind('click.rySlider.onStopClick', function () { stopSlider(container); return false; });
                        else
                            stop = $(opts.stopSelector).addClass(opts.stopButtonClass).bind('click.rySlider.onStopClick', function () { stopSlider(container); return false; });

                        if (!opts.autoPlay)
                            stop.addClass(opts.enabledClass);
                    }
                }
                // create pager buttons
                if (opts.renderPageButtons) {
                    var pageContainer, pageButtons = '';
                    if (opts.pageSelector == null)
                        pageContainer = $('<ul class="' + opts.pageContainerClass + '"></ul>').appendTo($wrapper);
                    else
                        pageContainer = $('<ul class="' + opts.pageContainerClass + '"></ul>').appendTo(opts.pageSelector);

                    for (i = 1; i <= pageCount; i = i + 1) {
                        var handleText = (opts.handleNames != null && opts.handleNames[i - 1] != null && opts.handleNames[i - 1] != undefined) ? opts.handleNames[i - 1] : i;
                        pageButtons += '<li><a class="' + 'page-' + i + ' ' + opts.pageButtonClass + '" href="#" name="' + i + '">' + handleText + '</a></li>';
                    }
                    pageContainer.append(pageButtons);
                    pageContainer.delegate('a', 'click.rySlider.onPageButtonClick', function (event) {
                        gotoPage(container, $(this).attr('name'), true);
                        return false;
                    });
                }

                if (opts.renderStateInfo) {
                    var stateContainer, tmpPageCount = pageCount;
                    if (opts.stateSelector == null)
                        stateContainer = $('<div class="' + opts.stateContainerClass + '"></div>').appendTo($wrapper);
                    else
                        stateContainer = $('<div class="' + opts.stateContainerClass + '"></div>').appendTo(opts.stateSelector);
                    $('<span class="currentPageNumber">' + currentPage + '</span>' + ' of ' + '<span class="totalPageCount">' + tmpPageCount + '</span>').appendTo(stateContainer);
                }

                if (opts.autoPlay)
                    playSlider(container);
            }
            else
                $wrapper.addClass(opts.notEnoughChildrenClass);
            updateIcons($(container));

            if (opts.afterCreateFunction != null && $.isFunction(opts.afterCreateFunction))
                opts.afterCreateFunction($(container), opts);

            return this;
        }; // END CREATE

        this.ScrollNext = function (goToAndStop) { nextSlide(this, opts.itemsToDisplay, goToAndStop); };
        this.ScrollPrevious = function (goToAndStop) { previousSlide(this, opts.itemsToDisplay, goToAndStop); };
        this.Play = function () { playSlider(this); };
        this.Stop = function () { stopSlider(this); };
        this.GotoPage = function (pageNumber, goToAndStop) { gotoPage(this, pageNumber, goToAndStop); };
        this.CurrentPage = function () { return currentPage; };
        this.PageCount = function () { return pageCount; };
        this.IsPlaying = function () { return playState; };

        // worker function to turn on autoPlay
        function playSlider(container) {
            var $container = $(container);
            if (!opts.enablePlayStop)
                return false;
            playInterval = setInterval(function () {
                nextSlide(container, opts.itemsToDisplay);
            }, opts.autoPlayInterval);
            if (opts.playSelector == null)
                $container.parent().find('.' + opts.playButtonClass).addClass(opts.enabledClass);
            else
                $(opts.playSelector).addClass(opts.enabledClass);
            if (opts.stopSelector == null)
                $container.parent().find('.' + opts.stopButtonClass).removeClass(opts.enabledClass);
            else
                $(opts.stopSelector).removeClass(opts.enabledClass);
            playState = true;
        }

        // a worker function to turn off autoPlay
        function stopSlider(container) {
            var $container = $(container);
            if (!opts.enablePlayStop)
                return false;
            clearInterval(playInterval);
            playInterval = null;

            if (opts.playSelector == null)
                $container.parent().find('.' + opts.playButtonClass).removeClass(opts.enabledClass);
            else
                $(opts.playSelector).removeClass(opts.enabledClass);
            if (opts.stopSelector == null)
                $container.parent().find('.' + opts.stopButtonClass).addClass(opts.enabledClass);
            else
                $(opts.stopSelector).addClass(opts.enabledClass);
            playState = false;
        }

        // Worker function to figure out whether a child element is 'shown' or not
        function addRemoveShowClass($item, $container) {
            if ($item.offset().left < $container.parent().offset().left || ($item.offset().left + $item.outerWidth(true)) > ($container.parent().offset().left + $container.parent().outerWidth()))
                $item.removeClass(opts.enabledClass);
            else
                $item.addClass(opts.enabledClass);
        }

        // Worker function to update the page icons
        function updateIcons($container) {
            var pageContainer, stateContainer;
            if (opts.pageSelector == null)
                pageContainer = $container.parent().find('.' + opts.pageContainerClass);
            else
                pageContainer = $(opts.pageSelector);
            pageContainer.find('a.' + opts.pageButtonClass + ':not(:eq(' + (currentPage - 1) + '))').removeClass(opts.enabledClass);
            pageContainer.find('a.' + opts.pageButtonClass + ':eq(' + (currentPage - 1) + ')').addClass(opts.enabledClass);

            if (opts.stateSelector == null)
                stateContainer = $container.parent().find('.' + opts.stateContainerClass);
            else
                stateContainer = $(opts.stateSelector);

            stateContainer.find('.currentPageNumber').html(currentPage);
            stateContainer.find('.totalPageCount').html(pageCount);

            if (currentPage == pageCount && opts.wrapSlider == false && opts.enablePlayStop == false)
                if (opts.nextSelector == null)
                    $container.parent().find('.' + opts.nextButtonClass).addClass(opts.disabledClass);
                else
                    $(opts.nextSelector).addClass(opts.disabledClass);
            else
                if (opts.nextSelector == null)
                    $container.parent().find('.' + opts.nextButtonClass).removeClass(opts.disabledClass);
                else
                    $(opts.nextSelector).removeClass(opts.disabledClass);

            if (currentPage == 1 && opts.wrapSlider == false && opts.enablePlayStop == false)
                if (opts.nextSelector == null)
                    $container.parent().find('.' + opts.prevButtonClass).addClass(opts.disabledClass);
                else
                    $(opts.prevSelector).addClass(opts.disabledClass);
            else
                if (opts.nextSelector == null)
                    $container.parent().find('.' + opts.prevButtonClass).removeClass(opts.disabledClass);
                else
                    $(opts.prevSelector).removeClass(opts.disabledClass);
        }

        // Wrapper function to move by page
        function gotoPage(container, page, stopAutoplay) {
            var difference = Math.abs((opts.itemsToDisplay * currentPage) - (opts.itemsToDisplay * page));
            if (difference > 0) {
                if (currentPage < page)
                    nextSlide(container, difference, stopAutoplay);
                else if (currentPage > page)
                    previousSlide(container, difference, stopAutoplay);
            }
        }

        // fade the sider, move it to the right position
        function resetSlider($container, pageNumber, fadeOutSpeed, fadeInSpeed) {
            if (opts.beforeResetFunction != null && $.isFunction(opts.beforeResetFunction))
                opts.beforeResetFunction($container, pageNumber, opts);

            $container.fadeOut(fadeOutSpeed, function () {
                $container.css({ left: (((opts.itemsToDisplay * (pageNumber - 1)) * slideWidth) * -1) });
                currentPage = pageNumber;
                $container.fadeIn(fadeInSpeed);
                updateIcons($container);
                if (opts.afterResetFunction != null && $.isFunction(opts.afterResetFunction))
                    opts.afterResetFunction($container, pageNumber, opts);
            });
        }

        // scrolls by item, not by page.
        function nextSlide(container, itemsToDisplay, stopAutoplay) {
            var $container = $(container);
            if ($container.children('.' + opts.contentClass + ':animated').size() > 0
                || $container.parent().find('.' + opts.containerClass + ':not(:animated)').size() != 1)
                return false;

            if (opts.beforeSlideFunction != null && $.isFunction(opts.beforeSlideFunction))
                opts.beforeSlideFunction($container, itemsToDisplay, opts, 'next');

            var newPage = currentPage, stopAutoplay = (stopAutoplay != true) ? false : true;
            var itemsToDisplay = (itemsToDisplay == null) ? opts.itemsToDisplay : itemsToDisplay;

            if (stopAutoplay)
                stopSlider(container);

            if (opts.wrapSlider) {
                $container.children(opts.contentElement + ':gt(' + (itemsToDisplay * 2) + ')').css('visibility', 'hidden').siblings().css('visibility', 'visible');
                // Slide container over
                $container.animate({ left: '-=' + (slideWidth * itemsToDisplay) },
                                        { duration: opts.speed, easing: opts.easingMethod, complete: function () {
                                            $container.children('.' + opts.contentClass).each(function () {
                                                addRemoveShowClass($(this), $container);
                                            });
                                            // reset stuff
                                            $container.css({ left: 0 });
                                            $container.children(opts.contentElement + ':lt(' + itemsToDisplay + ')').appendTo($container);
                                            $container.children('.' + opts.contentClass).css('left', function (index) {
                                                return (index * slideWidth) + parseInt($(this).css('margin-left'));
                                            });
                                            // change current page
                                            newPage += (itemsToDisplay / opts.itemsToDisplay);
                                            if (newPage > pageCount)
                                                newPage = newPage - pageCount;
                                            currentPage = newPage;
                                            updateIcons($container);

                                            if (opts.afterSlideFunction != null && $.isFunction(opts.afterSlideFunction))
                                                opts.afterSlideFunction($container, itemsToDisplay, opts, 'next');
                                        }
                                        });
            }
            else {
                if (newPage < pageCount) {
                    newPage += (itemsToDisplay / opts.itemsToDisplay);
                    // slide container over
                    $container.children(opts.contentElement + ':gt(' + (itemsToDisplay * 2) + ')').css('visibility', 'hidden').siblings().css('visibility', 'visible');
                    $container.animate({ left: '-=' + (slideWidth * itemsToDisplay) },
                                            { duration: opts.speed, easing: opts.easingMethod, complete: function () {
                                                $container.children('.' + opts.contentClass).each(function () {
                                                    addRemoveShowClass($(this), $container);
                                                });
                                                // reset stuff
                                                $container.children('.' + opts.contentClass).css('left', function (index) {
                                                    return (index * slideWidth) + parseInt($(this).css('margin-left'));
                                                });

                                                if (opts.afterSlideFunction != null && $.isFunction(opts.afterSlideFunction))
                                                    opts.afterSlideFunction($container, itemsToDisplay, opts, 'next');
                                            }
                                            });
                    currentPage = newPage;
                    updateIcons($container);
                }
                else if (newPage + (itemsToDisplay / opts.itemsToDisplay) > pageCount && opts.enablePlayStop == true) {
                    resetSlider($container, 1, 1000, 1000);
                }
            }
            if (stopAutoplay && opts.autoPlay == true)
                playSlider(container);
        }

        function previousSlide(container, itemsToDisplay, stopAutoplay) {
            var $container = $(container);
            if ($container.children('.' + opts.contentClass + ':animated').size() > 0
                || $container.parent().find('.' + opts.containerClass + ':not(:animated)').size() != 1)
                return false;

            if (opts.beforeSlideFunction != null && $.isFunction(opts.beforeSlideFunction))
                opts.beforeSlideFunction($container, itemsToDisplay, opts, 'previous');

            var itemsToDisplay = (itemsToDisplay == null) ? opts.itemsToDisplay : itemsToDisplay, newPage = currentPage, stopAutoplay = (stopAutoplay != true) ? false : true;

            if (stopAutoplay)
                stopSlider(container);

            if (opts.wrapSlider) {
                // shift container left to fit cells
                $container.css({ left: ((itemsToDisplay * slideWidth) * -1) });
                // prepend cells from end to start
                $($container.children(opts.contentElement).slice(itemsToDisplay * -1).get().reverse()).prependTo($container);
                // reset left values
                $container.children('.' + opts.contentClass).css('left', function (index) {
                    return (index * slideWidth) + parseInt($(this).css('margin-left'));
                });
                // scroll right
                $container.children(opts.contentElement + ':lt(' + (itemsToDisplay * 2) + ')').css('visibility', 'hidden').siblings().css('visibility', 'visible');
                $container.animate({ left: '+=' + (slideWidth * itemsToDisplay) },
                                        { duration: opts.speed, easing: opts.easingMethod, complete: function () {
                                            $container.children('.' + opts.contentClass).each(function () { addRemoveShowClass($(this), $container); });
                                            if (opts.afterSlideFunction != null && $.isFunction(opts.afterSlideFunction))
                                                opts.afterSlideFunction($container, itemsToDisplay, opts, 'previous');
                                        }
                                        });
                // drink champagne like a boss
                newPage -= (itemsToDisplay / opts.itemsToDisplay);
                if (newPage < 1)
                    newPage = pageCount - Math.abs(newPage);
                currentPage = newPage;
                updateIcons($container);
            }
            else {
                if (newPage > 1) {
                    newPage -= (itemsToDisplay / opts.itemsToDisplay);
                    // non-wrap code goes here
                    $container.animate({ left: '+=' + (slideWidth * itemsToDisplay) },
                                      { duration: opts.speed, easing: opts.easingMethod, complete: function () {
                                          $container.children('.' + opts.contentClass).each(function () {
                                              addRemoveShowClass($(this), $container);
                                          });
                                          if (opts.afterSlideFunction != null && $.isFunction(opts.afterSlideFunction))
                                              opts.afterSlideFunction($container, itemsToDisplay, opts, 'previous');
                                      }
                                      });
                    currentPage = newPage;
                    updateIcons($container);
                }
            }
            if (stopAutoplay && opts.autoPlay == true)
                playSlider(container);
        }

        // Finally
        return this.Create(i);
    };

    jQuery.fn.ryslider.defaults = {
        speed: 500,
        startItem: 1,
        itemsToDisplay: 1,
        wrapSlider: false,
        enablePlayStop: false,
        handleNames: null,
        autoPlay: false,
        autoPlayInterval: 1000,
        renderNext: true,
        nextSelector: null,
        renderPrevious: true,
        prevSelector: null,
        renderPageButtons: true,
        pageSelector: null,
        renderPlayButton: true,
        playSelector: null,
        renderStopButton: true,
        stopSelector: null,
        renderStateInfo: true,
        stateSelector: null,
        easingMethod: 'easeOutQuad',
        contentClass: 'slider_content',
        wrapperClass: 'slider_wrapper',
        containerClass: 'ryslider',
        nextButtonClass: 'next_button',
        prevButtonClass: 'previous_button',
        pageButtonClass: 'page_button',
        playButtonClass: 'play_button',
        stopButtonClass: 'stop_button',
        pageContainerClass: 'page_container',
        stateContainerClass: 'state_container',
        notEnoughChildrenClass: 'notEnoughChildren',
        enabledClass: 'active',
        disabledClass: 'disabled',
        contentElement: 'div',
        beforeSlideFunction: null,
        afterSlideFunction: null,
        beforeResetFunction: null,
        afterResetFunction: null,
        beforeCreateFunction: null,
        afterCreateFunction: null,
        beforeDestroyFunction: null,
        afterDestroyFunction: null
    };
})(jQuery);
