(function ($) {
    function SwipeSlider(element, options) {
        if ("ontouchstart" in window) {
            this.hasTouch = true
        } else {
            this.hasTouch = false
        }
        this.slider = $(element);
        var self = this;
        this.settings = $.extend({}, $.fn.swipeSlider.defaults, options);
        if (this.hasTouch) {
            this.settings.directionNavAutoHide = false;
            this.settings.hideArrowOnLastSlide = true
        }
        this.isSlideshowRunning = false;
        this._az = false;
        this._by = this.slider.find(".swipeSlidesContainer");
        this._cx = this._by.wrap('<div class="swipeWrapper"/>').parent();
        this.slides = this._by.find(".swipeSlide");
        this._dw = false;
        if (this.settings.removeCaptionsOpacityInIE8) {
            if ($.browser.msie && parseInt($.browser.version) <= 8) {
                this._dw = true
            }
        }
        this.slider.css("overflow", "visible");
        this.sliderWidth = 0;
        this.sliderHeight = 0;
        this.slideshowTimer = '';
        this.numSlides = this.slides.length;
        this.currentSlideId = 0;
        this.lastSlideId = -1;
        this.isAnimating = true;
        this._ev = 0;
        this._fu = 0;
        this._gt = [];
        this._hs = [];
        this._ir = false;
        this._jq = 0;
        this._kp = 0;
        this._lo = 0;
        this.mn = 0;
        this._az1 = false;
        this.wasSlideshowPlaying = false;
        this._cx1 = false;
        if (this.settings.slideshowEnabled) {
            if (this.settings.slideshowDelay > 0) {
                if (this.settings.slideshowPauseOnHover) {
                    this.slider.hover(function () {
                        self._cx1 = true;
                        self.stopSlideshow(true)
                    }, function () {
                        self._cx1 = false;
                        self.resumeSlideshow(true)
                    })
                }
            }
        }
        var cursCoords = "";
        if ($.browser.msie) {
            if (parseInt($.browser.version) == 7) {
                this.isIE7 = true;
                this._by.css("cursor", "move")
            } else {
                this.isIE7 = false
            }
        }
        if ($.browser.opera) {
            _dw1 = "move";
            _ev1 = "move"
        } else {
            if ($.browser.mozilla) {
                _dw1 = "-moz-grab";
                _ev1 = "-moz-grabbing"
            } else {
                _dw1 = "url(img/cursors/grab.cur), move";
                _ev1 = "url(img/cursors/grabbing.cur), move"
            }
            _dw1 = $.browser.mozilla ? "-moz-grab" : "url(img/cursors/grab.cur), move";
            _ev1 = $.browser.mozilla ? "-moz-grabbing" : "url(img/cursors/grabbing.cur), move"
        }
        this._fu1();
        if (this.settings.controlNavEnabled) {
            var _gt1;
            var _gt1Container;
            if (!self.settings.controlNavThumbs) {
                _gt1Container = $('<div class="swipeControlNavOverflow"><div class="swipeControlNavContainer"><div class="swipeControlNavCenterer"></div></div></div>');
                _gt1 = _gt1Container.find('.swipeControlNavCenterer')
            } else {
                if (self.settings.controlNavThumbsNavigation) {
                    _gt1Container = $('<div class="swipeControlNavOverflow swipeThumbs" style="left:42px; width:' + (this.slider.width() - 84) + 'px;"><div class="swipeControlNavThumbsContainer"></div></div>');
                    _gt1 = _gt1Container.find('.swipeControlNavThumbsContainer');
                    this._cx.after("<a href='#' class='thumbsArrow left disabled'></a>");
                    this._cx.after("<a href='#' class='thumbsArrow right'></a>")
                } else {
                    _gt1Container = $('<div class="swipeControlNavOverflow swipeThumbs"><div class="swipeControlNavContainer"><div class="swipeControlNavCenterer"></div></div></div>');
                    _gt1 = _gt1Container
                }
            }
            var cSlideId = 0;
            this.slides.each(function () {
                if (self.settings.controlNavThumbs) {
                    _gt1.append("<a href='#' class='swipeThumb' style='background-image:url(" + $(this).attr("data-thumb") + ");'/>")
                } else {
                    _gt1.append('<a href="#"/>')
                }
                cSlideId++
            });
            this.navItems = _gt1.children();
            this.navItems.eq(0).addClass("current");
            this.navItems.eq(this.navItems.length - 1).addClass("last");
            this._cx.after(_gt1Container);
            if (self.settings.controlNavThumbs && self.settings.controlNavThumbsNavigation) {
                this.thumbsArrowLeft = this.slider.find("a.thumbsArrow.left");
                this.thumbsArrowRight = this.slider.find("a.thumbsArrow.right");
                this._ir1 = _gt1;
                this._jq1 = parseInt(_gt1Container.width());
                this._kp1 = this.navItems.size();
                this._lo1 = this.navItems.eq(0).outerWidth(true);
                this.mn1 = this._lo1 * this._kp1;
                this._ir1.css("width", this.mn1 + "px");
                this._az2 = 0;
                this._by2 = Math.ceil(this.mn1 / this._jq1);
                this._cx2 = Math.floor(this._jq1 / this._lo1);
                this.thumbsArrowLeft.click(function (e) {
                    e.preventDefault();
                    if (self._az2 > 0) {
                        self._az2--;
                        self._dw2()
                    }
                });
                this.thumbsArrowRight.click(function (e) {
                    e.preventDefault();
                    if (self._az2 < self._by2 - 1) {
                        self._az2++;
                        self._dw2()
                    }
                })
            }
        }
        if (this.settings.captionAnimationEnabled) {
            this._cx.find(".swipeCaption").css("display", "none")
        }
        if (this.settings.directionNavEnabled) {
            this._cx.after("<a href='#' class='arrow left'/>");
            this._cx.after("<a href='#' class='arrow right'/>");
            this.arrowLeft = this.slider.find("a.arrow.left");
            this.arrowRight = this.slider.find("a.arrow.right");
            if (this.arrowLeft.length < 1 || this.arrowRight.length < 1) {
                this.settings.directionNavEnabled = false
            } else if (this.settings.directionNavAutoHide) {
                this.arrowLeft.hide();
                this.arrowRight.hide();
                this.slider.bind("mousemove.arrowshover", function () {
                    self.arrowLeft.fadeIn("fast");
                    self.arrowRight.fadeIn("fast");
                    self.slider.unbind("mousemove.arrowshover")
                });
                this.slider.hover(function () {
                    self.arrowLeft.fadeIn("fast");
                    self.arrowRight.fadeIn("fast")
                }, function () {
                    self.arrowLeft.fadeOut("fast");
                    self.arrowRight.fadeOut("fast")
                })
            }
            if (this.settings.hideArrowOnLastSlide) {
                this.arrowLeft.css("visibility", "hidden")
            }
        }
        var resizeTimer;
        $(window).bind('resize', function () {
            if (resizeTimer) clearTimeout(resizeTimer);
            resizeTimer = setTimeout(function () {
                self._ev2()
            }, 100)
        });
        this._ev2();
        if (this.settings.welcomeScreenEnabled) {
            var bgImageURL = this.slides.eq(0).css("background-image");
            if (bgImageURL != "" && bgImageURL != "none") {
                var imageObj = new Image();
                $(imageObj).load(function () {
                    self.settings.loadingComplete.call(self);
                    self.slider.find(".swipeLoadingScreen").fadeOut(self.settings.welcomeScreenShowSpeed, function () {
                        $(this).remove()
                    });
                    setTimeout(function () {
                        self._fu2()
                    }, self.settings.welcomeScreenShowSpeed + 100)
                });
                bgImageURL = bgImageURL.substring(4, bgImageURL.length - 1);
                if (bgImageURL.charAt(0) == '"' || bgImageURL.charAt(0) == "'") {
                    bgImageURL = bgImageURL.substring(1, bgImageURL.length - 1)
                }
                imageObj.src = bgImageURL
            } else {
                var loadingScreen = this.slider.find(".swipeLoadingScreen");
                if (loadingScreen) {
                    self.settings.loadingComplete.call(self);
                    loadingScreen.fadeOut(self.settings.welcomeScreenShowSpeed, function () {
                        $(this).remove()
                    });
                    setTimeout(function () {
                        self._fu2()
                    }, self.settings.welcomeScreenShowSpeed + 100)
                } else {
                    setTimeout(function () {
                        self._fu2();
                        self.slider.find(".swipeLoadingScreen").remove();
                        self.settings.loadingComplete.call(self)
                    }, 100)
                }
            }
        } else {
            setTimeout(function () {
                self._fu2();
                self.slider.find(".swipeLoadingScreen").remove();
                self.settings.loadingComplete.call(self)
            }, 100)
        }
    }
    SwipeSlider.prototype = {
        goTo: function (id) {
            if (!this.isAnimating) {
                this.isAnimating = true;
                var self = this;
                this._by.unbind("mousedown").unbind("touchstart").unbind("MozTouchDown");
                this._ir = true;
                if (this.settings.controlNavEnabled) {
                    this.navItems.eq(this.currentSlideId).removeClass('current');
                    this.navItems.eq(id).addClass("current")
                }
                this.lastSlideId = this.currentSlideId;
                this.currentSlideId = id;
                if (this.settings.directionNavEnabled && this.settings.controlNavThumbs && this.settings.controlNavThumbsNavigation) {
                    for (var i = 0; i < this._by2; i++) {
                        if (id >= this._cx2 * i && id < this._cx2 * (i + 1)) {
                            this._az2 = i;
                            this._dw2();
                            break
                        }
                    }
                }
                if (this.settings.directionNavEnabled) {
                    if (this.settings.hideArrowOnLastSlide) {
                        if (this.lastSlideId == 0) {
                            this.arrowLeft.css("visibility", "visible")
                        } else if (this.lastSlideId == this.numSlides - 1) {
                            this.arrowRight.css("visibility", "visible")
                        }
                        if (this.currentSlideId == 0) {
                            this.arrowLeft.css("visibility", "hidden")
                        } else if (this.currentSlideId == this.numSlides - 1) {
                            this.arrowRight.css("visibility", "hidden")
                        }
                    }
                }
                this.settings.beforeSlideChange.call(this);
                this.stopSlideshow();
                this._by.animate({
                    left: -this.currentSlideId * this.sliderWidth
                }, this.settings.slideTransitionSpeed, this.settings.slideTransitionEasing, function () {
                    self._gt2()
                })
            }
        },
        prev: function () {
            if (this.currentSlideId <= 0) {
                this.goTo(this.numSlides - 1)
            } else {
                this._hs2()
            }
        },
        next: function () {
            if (this.currentSlideId >= this.numSlides - 1) {
                this.goTo(0)
            } else {
                this._ir2()
            }
        },
        resumeSlideshow: function (playedFromHover) {
            if (this.settings.slideshowEnabled) {
                if (this.slideshowTimer == '') {
                    if (playedFromHover) {
                        if (!this._az) {
                            return
                        }
                    }
                    this.slideshowTimer = setInterval(function () {
                        self.next();
                    }, this.settings.slideshowDelay);
                    this.isSlideshowRunning = true;
                    var self = this;
                }
            }
        },
        stopSlideshow: function (stoppedFromHover) {
            if (this.settings.slideshowEnabled) {
                if (stoppedFromHover) {
                    this._az = this.isSlideshowRunning
                } else {
                    this._az = false;
                    this.isSlideshowRunning = false
                }
                clearInterval(this.slideshowTimer);
                this.slideshowTimer = ''
            }
        },
        _dw2: function () {
            if (this._az2 == 0) {
                this.thumbsArrowLeft.addClass("disabled")
            } else {
                this.thumbsArrowLeft.removeClass("disabled")
            }
            if (this._az2 == this._by2 - 1) {
                this.thumbsArrowRight.addClass("disabled")
            } else {
                this.thumbsArrowRight.removeClass("disabled")
            }
            var offset = -this._jq1 * this._az2;
            this._ir1.animate({
                left: offset + "px"
            }, this.settings.controlNavThumbsSpeed, this.settings.controlNavThumbsEasing)
        },
        _fu2: function () {
            var self = this;
            if (this.settings.controlNavEnabled) {
                this.navItems.bind("click", function (e) {
                    e.preventDefault();
                    if (!this._ir) self._jq2(e)
                })
            }
            if (this.settings.directionNavEnabled) {
                this.arrowRight.bind('click', function (e) {
                    e.preventDefault();
                    if (!this._ir) self.next()
                });
                this.arrowLeft.bind('click', function (e) {
                    e.preventDefault();
                    if (!this._ir) self.prev()
                })
            }
            this._gt2();
            if (this.settings.slideshowEnabled && !this.settings.slideshowAutoStart) {
                this.stopSlideshow()
            }
        },
        _fu1: function () {
            if (!this.isIE7) {
                this._by.css("cursor", _dw1)
            }
        },
        _kp2: function () {
            if (!this.isIE7) {
                this._by.css("cursor", _ev1)
            }
        },
        _ir2: function () {
            if (this.currentSlideId < this.numSlides - 1) {
                this.goTo(this.currentSlideId + 1)
            } else {
                this.goTo(this.currentSlideId)
            }
        },
        _hs2: function () {
            if (this.currentSlideId > 0) {
                this.goTo(this.currentSlideId - 1)
            } else {
                this.goTo(this.currentSlideId)
            }
        },
        _ev2: function () {
            var totalWidth = parseInt(this._cx.width());
            var totalHeight = parseInt(this._cx.height());
            if (totalWidth != this.sliderWidth || totalHeight != this.sliderHeight) {
                this.sliderWidth = totalWidth;
                this.slides.each(function () {
                    $(this).css({
                        height: totalHeight + "px",
                        width: totalWidth + "px"
                    })
                });
                this._by.css({
                    "left": -this.currentSlideId * this.sliderWidth,
                    width: this.sliderWidth * this.numSlides
                })
            }
        },
        _jq2: function (e) {
            this.goTo($(e.currentTarget).index())
        },
        _lo2: function (e) {
            if (!this._az1) {
                var point;
                if (this.hasTouch) {
                    var currTouches = e.originalEvent.touches;
                    if (currTouches && currTouches.length > 0) {
                        point = currTouches[0]
                    } else {
                        return false
                    }
                } else {
                    point = e;
                    e.preventDefault()
                }
                if (this.slideshowTimer != '') {
                    this.wasSlideshowPlaying = true;
                    this.stopSlideshow()
                } else {
                    this.wasSlideshowPlaying = false
                }
                this._kp2();
                this._az1 = true;
                var self = this;
                $(document).bind("mousemove touchmove MozTouchMove", function (e) {
                    self.mn2(e)
                });
                $(document).bind("mouseup touchend MozTouchRelease", function (e) {
                    self._az3(e)
                });
                this._jq = parseInt(this._by.css("left"));
                this._kp = point.clientX;
                this._lo = point.clientY;
                this.mn = parseInt(this._by.css("left"))
            }
            return false
        },
        mn2: function (e) {
            var point;
            if (this.hasTouch) {
                var touches = e.originalEvent.touches;
                if (touches.length > 1) {
                    return false
                }
                point = touches[0];
                if (Math.abs(point.clientY - this._lo) + 10 > Math.abs(point.clientX - this._kp)) {
                    return false
                }
                e.preventDefault()
            } else {
                point = e;
                e.preventDefault()
            }
            this._fu = this._ev;
            var distance = point.clientX - this._kp;
            if (this._fu != distance) {
                this._ev = distance
            }
            if (distance != 0) {
                if (this.currentSlideId == 0) {
                    if (distance > 0) {
                        distance = Math.sqrt(distance) * 5
                    }
                } else if (this.currentSlideId == (this.numSlides - 1)) {
                    if (distance < 0) {
                        distance = -Math.sqrt(-distance) * 5
                    }
                }
                this._by.css("left", this._jq + distance)
            }
            return false
        },
        _az3: function (e) {
            if (this.wasSlideshowPlaying) {
                this.resumeSlideshow()
            }
            if (this._az1) {
                this._az1 = false;
                this._fu1();
                this.endPos = parseInt(this._by.css("left"));
                this.isdrag = false;
                $(document).unbind("mousemove").unbind("touchmove").unbind("MozTouchMove").unbind("mouseup").unbind("touchend").unbind("MozTouchRelease");
                if (this.endPos == this.mn) {
                    return
                }
                if (this.mn - this.settings.minSlideOffset > this.endPos) {
                    if (this._fu < this._ev) {
                        this.goTo(this.currentSlideId);
                        return false
                    }
                    this._ir2()
                } else if (this.mn + this.settings.minSlideOffset < this.endPos) {
                    if (this._fu > this._ev) {
                        this.goTo(this.currentSlideId);
                        return false
                    }
                    this._hs2()
                } else {
                    this.goTo(this.currentSlideId)
                }
            }
            return false
        },
        _gt2: function () {
            var self = this;
            this.resumeSlideshow();
            this._ir = false;
            this._by.bind("mousedown touchstart MozTouchDown", function (e) {
                self._lo2(e)
            });
            if (this.settings.captionAnimationEnabled && this.lastSlideId != this.currentSlideId) {
                if (this.lastSlideId != -1) {
                    this.slides.eq(this.lastSlideId).find(".swipeCaption").css("display", "none")
                }
                setTimeout(function () {
                    self._by3(this.currentSlideId)
                }, 10)
            }
            this.isAnimating = false;
            this.settings.afterSlideChange.call(this)
        },
        _by3: function (id) {
            var caption = this.slides.eq(this.currentSlideId).find(".swipeCaption");
            if (caption.length) {
                caption.css("display", "block");
                var self = this;
                var currItem;
                var captionItems = caption.children();
                var fadeEnabled;
                var moveEnabled;
                var effectName;
                var effectsObject;
                var moveEffectProperty;
                var currEffects;
                var newEffectObj;
                var moveOffset;
                var delay;
                var speed;
                var easing;
                var moveProp;
                if (this._gt.length > 0) {
                    for (var a = this._gt.length - 1; a > -1; a--) {
                        clearTimeout(this._gt.splice(a, 1))
                    }
                }
                if (this._hs.length > 0) {
                    var cItemTemp;
                    for (var k = this._hs.length - 1; k > -1; k--) {
                        cItemTemp = this._hs[k];
                        if (cItemTemp != undefined) {
                            cItemTemp.captionItem.css(cItemTemp.css)
                        }
                        this._hs.splice(k, 1)
                    }
                }
                for (var i = 0; i < captionItems.length; i++) {
                    currItem = $(captionItems[i]);
                    effectsObject = {};
                    fadeEnabled = false;
                    moveEnabled = false;
                    moveEffectProperty = "";
                    if (currItem.attr("data-show-effect") == undefined) {
                        currEffects = this.settings.captionShowEffects
                    } else {
                        currEffects = currItem.attr("data-show-effect").split(" ")
                    }
                    for (var q = 0; q < currEffects.length; q++) {
                        if (fadeEnabled && moveEnabled) {
                            break
                        }
                        effectName = currEffects[q].toLowerCase();
                        if (!fadeEnabled && effectName == "fade") {
                            fadeEnabled = true;
                            effectsObject['opacity'] = 1
                        } else if (moveEnabled) {
                            break
                        } else if (effectName == "movetop") {
                            moveEffectProperty = "margin-top"
                        } else if (effectName == "moveleft") {
                            moveEffectProperty = "margin-left"
                        } else if (effectName == "movebottom") {
                            moveEffectProperty = "margin-bottom"
                        } else if (effectName == "moveright") {
                            moveEffectProperty = "margin-right"
                        }
                        if (moveEffectProperty != "") {
                            effectsObject['moveProp'] = moveEffectProperty;
                            effectsObject['moveStartPos'] = parseInt(currItem.css(moveEffectProperty));
                            moveEnabled = true
                        }
                    }
                    moveOffset = parseInt(currItem.attr("data-move-offset"));
                    if (isNaN(moveOffset)) {
                        moveOffset = this.settings.captionMoveOffset
                    }
                    delay = parseInt(currItem.attr("data-delay"));
                    if (isNaN(delay)) {
                        delay = self.settings.captionShowDelay * i + 10
                    }
                    speed = parseInt(currItem.attr("data-speed"));
                    if (isNaN(speed)) {
                        speed = self.settings.captionShowSpeed
                    }
                    easing = currItem.attr("data-easing");
                    if (easing == undefined) {
                        easing = self.settings.captionShowEasing
                    }
                    newEffectObj = {};
                    if (moveEnabled) {
                        moveProp = effectsObject.moveProp;
                        if (moveProp == "margin-right") {
                            moveProp = "margin-left";
                            newEffectObj[moveProp] = effectsObject.moveStartPos + moveOffset + "px"
                        } else if (moveProp == "margin-bottom") {
                            moveProp = "margin-top";
                            newEffectObj[moveProp] = effectsObject.moveStartPos + moveOffset + "px"
                        } else {
                            newEffectObj[moveProp] = effectsObject.moveStartPos - moveOffset + "px"
                        }
                    }
                    if (!self._dw && fadeEnabled) {
                        newEffectObj.opacity = 0
                    }
                    currItem.hide().css(newEffectObj);
                    if (moveEnabled) {
                        newEffectObj[moveProp] = effectsObject.moveStartPos + "px"
                    }
                    if (!self._dw && fadeEnabled) {
                        newEffectObj.opacity = 1
                    }
                    this._hs.push({
                        captionItem: currItem,
                        css: newEffectObj
                    });
                    this._gt.push(setTimeout((function (cItem, animateData, cSpeed, cEasing, cId, objFadeEnabled) {
                        return function () {
                            delete self._hs[cId];
                            cItem.show().animate(animateData, cSpeed, cEasing)
                        }
                    })(currItem, newEffectObj, speed, easing, i, fadeEnabled), delay))
                }
            }
        }
    };
    $.fn.swipeSlider = function (options) {
        return this.each(function () {
            var swipeSlider = new SwipeSlider($(this), options);
            $(this).data("swipeSlider", swipeSlider)
        })
    };
    $.fn.swipeSlider.defaults = {
        directionNavEnabled: true, //Next/Previous
        directionNavAutoHide: false, //Show on Hover
        slideTransitionSpeed: 400,
        slideTransitionEasing: "easeInOutSine",
        captionAnimationEnabled: true,
        captionShowEffects: ["fade", "moveleft"],
        captionMoveOffset: 20,
        captionShowSpeed: 400,
        captionShowEasing: "easeOutCubic",
        captionShowDelay: 200,
        controlNavEnabled: true, //Bullets
        controlNavThumbs: false, //Thumbnails
        controlNavThumbsNavigation: true,
        controlNavThumbsSpeed: 400,
        controlNavThumbsEasing: "easeInOutSine",
        slideshowEnabled: false, //Auto-play
        slideshowDelay: 5000,
        slideshowPauseOnHover: true,
        slideshowAutoStart: true,
        welcomeScreenEnabled: true,
        welcomeScreenShowSpeed: 500,
        minSlideOffset: 20,
        hideArrowOnLastSlide: false,
        removeCaptionsOpacityInIE8: false,
        beforeSlideChange: function () { },
        afterSlideChange: function () { },
        loadingComplete: function () { }
    };
    $.fn.swipeSlider.settings = {}
})(jQuery);
