/*
 * scrollingCarousel 1.5 - jQuery plugin
 * Written by Adam Lafene
 *
 * Copyright (c) 2010 Adam Lafene - www.convergent-evolution.co.uk
 *
 * Licensed under the terms of the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
(function ($) {
    $.fn.scrollingCarousel = function (options) {
        var method;
        if ((typeof options).toLowerCase() === 'object' || !options) {
            var defaults = {
                scrollerOffset: 0,
                scrollSpeed: 'medium',
                looped: true
            };
            options = $.extend(defaults, options)
        } else {
            method = options
        }
        return this.each(function (i) {
            var scrollerContent;
            var scrollSwitch = 0;
            var scrollerPosition;
            var sMultiplier;
            var scrollerChildren;
            var offSetDistance;
            var scrollDistance;
            var centerPoint;
            var functions = new Object();
            obj = $(this);
            if (!method) {
                if (!obj.attr('id')) {
                    obj.attr('id', 'scrollingCarouselElement_' + carouselCount)
                }
            }
            var objId = obj.attr('id');
            var scrollContainer = obj[0];
            scrollContainer.style.paddingLeft = '0';
            scrollContainer.style.paddingRight = '0';
            var scrollContainerWidth = scrollContainer.offsetWidth;
            var childType = obj.children()[0].nodeName.toLowerCase();
            switch (childType) {
            case 'div':
                if (!method) {
                    scrollContainer.innerHTML = '<div class="sc_scrollContent">' + obj[0].innerHTML + '</div>';
                    scrollContainer.innerHTML += scrollContainer.innerHTML
                }
                scrollerContent = obj.find('div.sc_scrollContent');
                scrollerChildren = obj.find('div.sc_scrollContent:first').find('div');
                break;
            case 'ul':
                if (!method) {
                    scrollContainer.innerHTML += scrollContainer.innerHTML
                }
                scrollerContent = obj.find('ul');
                scrollerChildren = obj.find('ul:first').find('li');
                break;
            case 'ol':
                if (!method) {
                    scrollContainer.innerHTML += scrollContainer.innerHTML
                }
                scrollerContent = obj.find('ol');
                scrollerChildren = obj.find('ol:first').find('li');
                break;
            default:
                alert('unable to initialise scroller - please ensure contents are either in a UL, an OL or in DIVs');
                return
            }
            switch (options.scrollSpeed) {
            case 'slow':
                sMultiplier = 1;
                break;
            case 'fast':
                sMultiplier = 4;
                break;
            case 'medium':
            default:
                sMultiplier = 2
            }
            var scrollContentWidth = 0;
            var scrollerHeight = 0;
            var itemPadding;
            var itemMargin;
            $(scrollerChildren).each(function (i) {
                scrollContentWidth += $(this, obj)[0].offsetWidth + parseInt($(this, obj).css('marginLeft')) + parseInt($(this, obj).css('marginRight'));
                if ($(this, obj)[0].offsetHeight > scrollerHeight) {
                    scrollerHeight = $(this, obj)[0].offsetHeight
                }
            });
            if (!method) {
                if (scrollContentWidth > obj[0].offsetWidth) {
                    var offSetPoint = Math.round((scrollContentWidth / 100) * options.scrollerOffset);
                    offSetDistance = offSetPoint - (Math.round(scrollContainerWidth / 2));
                    if (offSetDistance > (scrollContentWidth - scrollContainerWidth)) {
                        offSetDistance = scrollContentWidth - scrollContainerWidth
                    }
                } else {
                    $(scrollerContent[1]).remove();
                    return
                }
                scrollContainer.style.overflow = 'hidden';
                scrollContainer.style.position = 'relative';
                scrollContainer.style.height = scrollerHeight + 'px';
                var itemPadding;
                scrollerContent.each(function () {
                    $(this, obj)[0].style.position = 'absolute';
                    $(this, obj)[0].style.top = '0';
                    $(this, obj)[0].style.width = scrollContentWidth + 'px';
                    $(this).children().each(function (i) {
                        $(this, obj)[0].style.cssFloat = 'left';
                        $(this, obj)[0].style.position = 'static'
                    })
                });
                scrollerContent[0].style.left = (offSetDistance > 0) ? '-' + offSetDistance + 'px' : '0';
                if (options.looped == true) {
                    scrollerContent[1].style.left = scrollerContent[0].offsetLeft - scrollContentWidth + 'px'
                } else {
                    scrollerContent[1].style.display = 'none';
                    scrollerContent[1].style.top = '-1000px'
                }
                obj.mouseenter(function () {
                    functions.startCarousel()
                });
                obj.mouseleave(function () {
                    functions.stopCarousel(true)
                });
                obj.mousemove(function (e) {
                    var cursor = {
                        x: 0,
                        y: 0
                    };
                    
                    var $currentTarget = $(e.currentTarget);
                    if (e.pageX || e.pageY) {
                        cursor.x = e.pageX;
                        cursor.y = e.pageY;
                    } else if ($currentTarget.data('pageX') || $currentTarget.data('pageY')) {
                        cursor.x = $currentTarget.data('pageX');
                        cursor.y = $currentTarget.data('pageY');
                    } else {
                        var de = document.documentElement;
                        var b = document.body;
                        cursor.x = e.clientX + ((de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0));
                        cursor.y = e.clientY + ((de.scrollTop || b.scrollTop) - (de.clientTop || 0))
                    }
                    cursorPosition = cursor;
                })
            }
            functions.startCarousel = function () {
                centerPoint = Math.round($(scrollContainer).offset().left + (scrollContainer.offsetWidth / 2));
                scrollerPosition = scrollerPosition ? scrollerPosition : parseInt(scrollerContent[0].style.left);
                scrollerInterval[objId] = setInterval(function () {
                    var cursorDistance;
                    var cursor = cursorPosition.x;
                    var halfContainer = scrollContainerWidth / 2;
                    cursorDistance = (cursor < centerPoint) ? centerPoint - cursor : cursor - centerPoint;
                    scrollDistance = (cursorDistance < (Math.ceil((halfContainer / 100) * 30))) ? 1 : ((cursorDistance < (Math.ceil((halfContainer / 100) * 50))) ? 2 * sMultiplier : ((cursorDistance < (Math.ceil((halfContainer / 100) * 70))) ? 3 * sMultiplier : ((cursorDistance < (Math.ceil((halfContainer / 100) * 90))) ? 4 * sMultiplier : 6 * sMultiplier)));
                    if (cursor < centerPoint) {
                        if ((scrollerPosition + scrollDistance) > 0 && options.looped == false) {
                            scrollerPosition = 0
                        } else if ((scrollerPosition + scrollDistance) > scrollContentWidth) {
                            scrollerPosition = 0;
                            scrollSwitch = (scrollSwitch == 0) ? 1 : 0
                        } else {
                            scrollerPosition = scrollerPosition + scrollDistance
                        }
                    } else if (cursor > centerPoint) {
                        if ((scrollerPosition - scrollDistance) < (0 - (scrollContentWidth - scrollContainerWidth))) {
                            if (options.looped == false) {
                                scrollerPosition = (0 - (scrollContentWidth - scrollContainerWidth))
                            } else {
                                scrollerPosition = scrollContainerWidth;
                                scrollSwitch = (scrollSwitch == 0) ? 1 : 0
                            }
                        } else {
                            scrollerPosition = scrollerPosition - scrollDistance
                        }
                    }
                    scrollerContent[scrollSwitch].style.left = scrollerPosition + 'px';
                    scrollerContent[(scrollSwitch == 0) ? 1 : 0].style.left = scrollerPosition - scrollContentWidth + 'px'
                }, 40)
            };
            functions.stopCarousel = function (easing) {
                if (!scrollerInterval[objId]) {
                    return
                }
                clearInterval(scrollerInterval[objId]);
                scrollerInterval[objId] = 0;
                if (!easing || options.looped == false) {
                    return
                }
                if (scrollDistance > 1) {
                    var i;
                    var brakingDistance = 0;
                    for (i = scrollDistance; i > 1; i--) {
                        brakingDistance += i
                    }
                    if (cursorPosition.x < centerPoint) {
                        if ((scrollerPosition + brakingDistance) > scrollContentWidth) {
                            scrollerPosition = scrollerPosition - scrollContentWidth;
                            scrollSwitch = (scrollSwitch == 0) ? 1 : 0
                        }
                    } else {
                        if ((scrollerPosition - brakingDistance) < (0 - (scrollContentWidth - scrollContainerWidth))) {
                            scrollerPosition = scrollerPosition + scrollContentWidth;
                            scrollSwitch = (scrollSwitch == 0) ? 1 : 0
                        }
                    }
                    var ivl = setInterval(function () {
                        if (scrollDistance > 1) {
                            if (cursorPosition.x < centerPoint) {
                                scrollerPosition += scrollDistance
                            } else {
                                scrollerPosition -= scrollDistance
                            }
                            scrollerContent[scrollSwitch].style.left = scrollerPosition + 'px';
                            scrollerContent[(scrollSwitch == 0) ? 1 : 0].style.left = scrollerPosition - scrollContentWidth + 'px';
                            scrollDistance--
                        } else {
                            clearInterval(ivl)
                        }
                    }, 50)
                }
            };
            if (!method) {
                carouselCount++;
                return
            }
            switch (method) {
            case 'pause':
                functions.stopCarousel();
                obj.unbind('mouseenter');
                obj.unbind('mouseleave');
                break;
            case 'play':
                $('html').mousemove(function (e) {
                    var cursor = {
                        x: 0,
                        y: 0
                    };
                    
                    var $currentTarget = $(e.currentTarget);
                    if (e.pageX || e.pageY) {
                        cursor.x = e.pageX;
                        cursor.y = e.pageY
                    } else if ($currentTarget.data('pageX') || $currentTarget.data('pageY')) {
                        cursor.x = $currentTarget.data('pageX');
                        cursor.y = $currentTarget.data('pageY');
                    } else {
                        var de = document.documentElement;
                        var b = document.body;
                        cursor.x = e.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
                        cursor.y = e.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0)
                    }
                    cursorPosition = cursor;
                    if (cursorPosition.x >= obj.offset().left && cursorPosition.x <= (obj.offset().left + obj[0].offsetWidth) && cursorPosition.y >= obj.offset().top && cursorPosition.y <= (obj.offset().top + obj[0].offsetHeight)) {
                        functions.startCarousel();
                        obj.mouseenter(function () {
                            functions.startCarousel()
                        })
                    } else {
                        obj.mouseenter(function () {
                            functions.startCarousel()
                        })
                    }
                    obj.mouseleave(function () {
                        functions.stopCarousel(true)
                    });
                    $(this).unbind('mousemove')
                });
                break;
            case 'remove':
                if (obj.attr('id').indexOf('scrollingCarouselElement_') != (-1)) {
                    obj.attr('id', '')
                }
                obj.children(':eq(1)').remove();
                if ($('div.sc_scrollContent')[0]) {
                    obj[0].innerHTML = $('div.sc_scrollContent')[0].innerHTML;
                    obj.children().each(function () {
                        $(this, obj)[0].style.cssText = ''
                    })
                } else {
                    obj.find('li').each(function () {
                        $(this, obj)[0].style.cssText = ''
                    })
                }
                obj.children()[0].style.cssText = '';
                obj[0].style.cssText = '';
                obj.unbind();
                break;
            default:
                $.error('Method ' + method + ' does not exist on jQuery.scrollingCarousel')
            }
        })
    };
    var scrollerInterval = new Array();
    var cursorPosition;
    var carouselCount = 0
})(jQuery);
