/*
 * jQuery Infinite Carousel
 * @author admin@catchmyfame.com - http://www.catchmyfame.com
 * @version 2.0.2
 * @date June 12, 2010
 * @category jQuery plugin
 * @copyright (c) 2009 admin@catchmyfame.com (www.catchmyfame.com)
 * @license CC Attribution-Share Alike 3.0 - http://creativecommons.org/licenses/by-sa/3.0/
 */

;(function ($) {
  $.fn.extend({
    infiniteCarousel: function (options) {
      var defaults = {
        transitionSpeed: 800,
        displayTime: 6000,
        textholderHeight: 0.25,
        displayProgressBar: true,
        displayThumbnails: true,
        displayThumbnailNumbers: true,
        displayThumbnailBackground: true,
        thumbnailWidth: "20px",
        thumbnailHeight: "20px",
        thumbnailFontSize: ".7em",
        easeLeft: "linear",
        easeRight: "linear",
        imagePath: "/js/infinitecarousel/images/",
        inView: 1,
        padding: "0px",
        advance: 1,
        showControls: true,
        autoHideControls: false,
        autoHideCaptions: false,
        autoStart: true,
        prevNextInternal: true,
        enableKeyboardNav: true,
        onSlideStart: function () {},
        onSlideEnd: function () {},
        onPauseClick: function () {},
      }
      var options = $.extend(defaults, options)

      return this.each(function () {
        var randID = Math.round(Math.random() * 100000000)
        var o = options
        var obj = $(this)
        var autopilot = o.autoStart

        var numImages = $("img", obj).length // Number of images
        var imgHeight = $("img:first", obj).height()
        var imgWidth = $("img:first", obj).width()

        if (o.inView > numImages - 1) o.inView = numImages - 1 // check to make sure inview isnt greater than the number of images. inview should be at least two less than numimages (otherwise hinting wont work and animating left may catch a flash), but one less can work
        $("p", obj).hide() // Hide any text paragraphs in the carousel
        $(obj)
          .css({ position: "relative", overflow: "hidden" })
          .width(imgWidth * o.inView + o.inView * parseInt(o.padding) * 2)
          .height(imgHeight + parseInt(o.padding) * 2) //,'overflow':'hidden'
        $("ul", obj)
          .css({
            "list-style": "none",
            margin: "0",
            padding: "0",
            position: "relative",
          })
          .width(imgWidth * numImages)
        $("li", obj).css({
          display: "inline",
          float: "left",
          padding: o.padding,
        })

        // Move rightmost image over to the left
        $("li:last", obj).prependTo($("ul", obj))
        $("ul", obj)
          .css("left", -imgWidth - parseInt(o.padding) * 2 + "px")
          .width(9999)

        // Build progress bar
        if (o.displayProgressBar) {
          $(obj).append(
            '<div id="progress' +
              randID +
              '" class="ic-progress-bar" style="position:absolute;bottom:0;background:#bbb;left:0;z-index:1"></div>',
          )
          $("#progress" + randID)
            .width("100%")
            .height(5)
            .css("opacity", ".6")
        }

        // Animate progress bar
        function startProgressBar(barTime) {
          barTime = barTime == null ? o.displayTime : barTime
          $("#progress" + randID)
            .width("100%")
            .height(5)
          $("#progress" + randID).animate({ width: 0 }, barTime)
        }

        // Build textholder div(s) as wide as one image and as tall as the textholderHeight option
        var containerBorder =
          parseInt($(obj).css("border-bottom-width")) +
          parseInt($(obj).css("border-top-width"))
        if (isNaN(containerBorder)) containerBorder = 0 // IE returns NaN for $(obj).css('border-bottom-width')
        var containerPaddingLeft = parseInt($(obj).css("padding-left")) // Normally we'd do both left and right but only left matters here
        for (i = 1; i <= o.inView; i++) {
          $(obj).append(
            '<div id="textholder' +
              randID +
              "_" +
              i +
              '" class="textholder" style="position:absolute;width:' +
              imgWidth +
              "px;bottom:0px;margin-bottom:" +
              -(imgHeight * o.textholderHeight + containerBorder) +
              'px;"><span></span></div>',
          )
          $("#textholder" + randID + "_" + i).css({
            left: (i - 1) * (imgWidth + parseInt(o.padding) * 2),
            "margin-left": parseInt(o.padding) + containerPaddingLeft,
            "margin-right": o.padding,
          })
          $("#textholder" + randID + "_" + i)
            .height(imgHeight * o.textholderHeight)
            .css({ backgroundColor: "#FFF", opacity: "0.5" })
          html =
            '<div class="minmax" id="minmax' +
            randID +
            "_" +
            i +
            '" style="width:8px;height:8px;position:absolute;top:1px;right:10px;cursor:pointer;background:url(' +
            o.imagePath +
            'caption.gif) no-repeat 0 -8px"></div>'
          html +=
            '<div class="close" id="close' +
            randID +
            "_" +
            i +
            '" style="width:8px;height:8px;position:absolute;top:1px;right:1px;cursor:pointer;background:url(' +
            o.imagePath +
            'caption.gif) no-repeat 0 0"></div>'
          $("#textholder" + randID + "_" + i).append(html)
          $("#minmax" + randID + "_" + i).hide()
          $("#close" + randID + "_" + i).hide()
          if (!o.autoHideCaptions)
            showtext($("li:eq(" + i + ") p", obj).html(), i)
        }
        var textholderPadding =
          parseInt($("#textholder" + randID + "_1").css("padding-left")) +
          parseInt($("#textholder" + randID + "_1").css("padding-right"))
        if (textholderPadding > 0)
          $(".textholder", obj).width(imgWidth - textholderPadding)

        $(".close", obj).each(function (i) {
          // Need to use each() because a loop doesn't work in this situation. see http://www.bennadel.com/blog/534-The-Beauty-Of-The-jQuery-Each-Method.htm
          $(this).click(function () {
            $("#textholder" + randID + "_" + (i + 1)).animate(
              {
                marginBottom:
                  -imgHeight * o.textholderHeight - containerBorder - 1 + "px",
              },
              500,
            )
          })
        })
        $(".minmax", obj).each(function (i) {
          // Same reason as previous chunk
          $(this).click(function () {
            if (
              parseInt(
                $("#textholder" + randID + "_" + (i + 1)).css("margin-bottom"),
              ) == 0
            ) {
              $("#textholder" + randID + "_" + (i + 1)).animate(
                {
                  marginBottom:
                    -imgHeight * o.textholderHeight -
                    containerBorder +
                    12 +
                    "px",
                },
                500,
                function () {
                  $("#minmax" + randID + "_" + (i + 1)).css(
                    "background-position",
                    "0 -16px",
                  )
                },
              )
            } else {
              $("#textholder" + randID + "_" + (i + 1)).animate(
                { marginBottom: "0px" },
                500,
                function () {
                  $("#minmax" + randID + "_" + (i + 1)).css(
                    "background-position",
                    "0 -8px",
                  )
                },
              )
            }
          })
        })

        function showtext(t, i) {
          if (autopilot) {
            $("#minmax" + randID + "_" + i).hide()
            $("#close" + randID + "_" + i).hide()
          }
          if (t != null) {
            $("#textholder" + randID + "_" + i + " span").html(t) // Change textholder content
            $("#textholder" + randID + "_" + i)
              .stop()
              .animate({ marginBottom: "0px" }, 500) // Raise textholder
            $("#minmax" + randID + "_" + i).css("background-position", "0 -8px")
            showminmax()
          }
        }

        function showminmax() {
          if (!autopilot) {
            $(".minmax", obj).fadeIn(250)
            $(".close", obj).fadeIn(250)
          }
        }

        function hideCaption() {
          $(".textholder", obj)
            .stop()
            .animate(
              {
                marginBottom:
                  -imgHeight * o.textholderHeight - containerBorder - 1 + "px",
              },
              o.transitionSpeed,
            )
        }

        if (o.displayThumbnails) {
          function thumbclick(event) {
            target_num = this.id.split("_") // we want target_num[1]
            if (viewable[0] != target_num[1]) {
              status = "pause"
              $("#progress" + randID)
                .stop()
                .fadeOut()
              clearTimeout(clearInt)
              $("#thumbs" + randID + " div")
                .css({ cursor: "default" })
                .unbind("click") // Unbind the thumbnail click event until the transition has ended
              autopilot = 0
              setTimeout(function () {
                $("#play_pause_btn" + randID).css(
                  "background-position",
                  "0 -16px",
                )
              }, o.transitionSpeed)
              $("#play_pause_btn" + randID)
                .unbind("click")
                .bind("click", function () {
                  forceStart()
                })
            }
            if (target_num[1] > viewable[0]) {
              diff = target_num[1] - viewable[0]
              moveLeft(diff)
            }
            if (target_num[1] < viewable[0]) {
              diff = viewable[0] - target_num[1]
              moveRight(diff)
            }
          }

          var viewable = [] // track which images are being displayed
          var unviewable = [] // track which images are being displayed
          // Build thumbnail viewer and thumbnail divs
          $(obj).after(
            '<div id="thumbs' +
              randID +
              '" style="position:relative;overflow:auto;clear:left;text-align:left;padding-top:5px;"></div>',
          )
          for (i = 0; i <= numImages - 1; i++) {
            thumb = $("img:eq(" + (i + 1) + ")", obj).attr("src")
            $("#thumbs" + randID).append(
              '<div class="thumb" id="thumb' +
                randID +
                "_" +
                (i + 1) +
                '" style="cursor:pointer;background-image:url(' +
                thumb +
                ");display:inline;float:left;width:" +
                o.thumbnailWidth +
                ";height:" +
                o.thumbnailHeight +
                ";line-height:" +
                o.thumbnailHeight +
                ";padding:0;overflow:hidden;text-align:center;border:2px solid #ccc;margin-right:4px;font-size:" +
                o.thumbnailFontSize +
                ';font-family:Arial;color:#000;text-shadow:0 0 3px #fff">' +
                (i + 1) +
                "</div>",
            )
            if (i <= o.inView)
              $("#thumb" + randID + "_" + i).css({ "border-color": "#ff0000" })
            unviewable.push(i + 1)
          }
          // Initialize viewable/unviewable arrays
          for (i = 1; i <= o.inView; i++) viewable.push(unviewable.shift())

          // Next two lines are a special case to handle the first list element which was originally the last
          thumb = $("img:first", obj).attr("src")
          $("#thumb" + randID + "_" + numImages).css({
            "background-image": "url(" + thumb + ")",
          })
          $("#thumbs" + randID + " div.thumb:not(:first)").css({
            opacity: 0.65,
          }) // makes all thumbs 65% opaque except the first one

          $("#thumbs" + randID + " div.thumb").hover(
            function () {
              $(this).animate({ opacity: 1 }, 150)
            },
            function () {
              if (viewable[0] != this.id.split("_")[1])
                $(this).animate({ opacity: 0.65 }, 250)
            },
          ) // add hover to thumbs
          // Assign click handler for the thumbnails. Normally the format $('.thumb') would work but since it's outside of our object (obj) it would get called multiple times
          $("#thumbs" + randID + " div").bind("click", thumbclick) // We use bind instead of just plain click so that we can repeatedly remove and reattach the handler

          if (!o.displayThumbnailNumbers)
            $("#thumbs" + randID + " div").text("")
          if (!o.displayThumbnailBackground)
            $("#thumbs" + randID + " div").css({ "background-image": "none" })
        }

        if (o.showControls) {
          // Pause/play button(img)
          html =
            '<div id="play_pause_btn' +
            randID +
            '" style="cursor:pointer;position:absolute;top:3px;right:3px;border:none;width:16px;height:16px;background:url(' +
            o.imagePath +
            'playpause.gif) no-repeat 0 0"></div>'
          $(obj).append(html)
          var status = "play"
          $("#play_pause_btn" + randID)
            .css("opacity", 0.5)
            .hover(
              function () {
                $(this).animate({ opacity: "1" }, 250)
              },
              function () {
                $(this).animate({ opacity: ".5" }, 250)
              },
            )
          $("#play_pause_btn" + randID).click(function () {
            status = status == "play" ? "pause" : "play"
            status == "play" ? forceStart() : forcePause()
          })

          if (!o.prevNextInternal) {
            wrapID = $(obj).attr("id") + "Wrapper"
            $(obj)
              .wrap('<div id="' + wrapID + '"></div>')
              .css("margin", "0 auto")
            $("#" + wrapID)
              .css("position", "relative")
              .width(
                $(obj).width() +
                  40 +
                  parseInt($(obj).css("padding-left")) +
                  parseInt($(obj).css("padding-right")),
              )
          }

          // Prev/next button(img)
          arrowsTop = imgHeight / 2 - 15 + parseInt(o.padding)
          html =
            '<div id="btn_rt' +
            randID +
            '" style="position:absolute;right:2px;top:' +
            arrowsTop +
            "px;cursor:pointer;border:none;width:13px;height:30px;background:url(" +
            o.imagePath +
            'leftright.gif) no-repeat 0 0"></div>'
          html +=
            '<div id="btn_lt' +
            randID +
            '" style="position:absolute;left:2px;top:' +
            arrowsTop +
            "px;cursor:pointer;border:none;width:13px;height:30px;background:url(" +
            o.imagePath +
            'leftright.gif) no-repeat -13px 0"></div>'
          o.prevNextInternal
            ? $(obj).append(html)
            : $("#" + wrapID).append(html)

          $("#btn_rt" + randID)
            .css("opacity", 0.5)
            .click(function () {
              forcePrevNext("next")
            })
            .hover(
              function () {
                $(this).animate({ opacity: "1" }, 250)
              },
              function () {
                $(this).animate({ opacity: ".5" }, 250)
              },
            )
          $("#btn_lt" + randID)
            .css("opacity", 0.5)
            .click(function () {
              forcePrevNext("prev")
            })
            .hover(
              function () {
                $(this).animate({ opacity: "1" }, 250)
              },
              function () {
                $(this).animate({ opacity: ".5" }, 250)
              },
            )

          if (o.autoHideControls && o.prevNextInternal) {
            function showcontrols() {
              $("#play_pause_btn" + randID)
                .stop()
                .animate({ top: "3px", right: "3px" }, 250)
              $("#btn_rt" + randID)
                .stop()
                .animate({ top: arrowsTop + "px", right: "2px" }, 250)
              $("#btn_lt" + randID)
                .stop()
                .animate({ top: arrowsTop + "px", left: "2px" }, 250)
            }
            function hidecontrols() {
              $("#play_pause_btn" + randID)
                .stop()
                .animate(
                  {
                    top: -16 - containerBorder + "px",
                    right: -16 - containerBorder + "px",
                  },
                  250,
                )
              $("#btn_rt" + randID)
                .stop()
                .animate({ right: "-16px" }, 250)
              $("#btn_lt" + randID)
                .stop()
                .animate({ left: "-16px" }, 250)
            }
            $(obj).hover(showcontrols, hidecontrols)
            hidecontrols()
          }
          if (o.autoHideCaptions) {
            var isHover
            function autoShowCap() {
              isHover = true
              for (i = 1; i <= o.inView; i++)
                showtext($("li:eq(" + i + ") p", obj).html(), i)
            }
            function autoHideCap() {
              isHover = false
              hideCaption()
            }
            $(obj).hover(autoShowCap, autoHideCap)
            hideCaption()
          }
        }

        function keyBind() {
          if (o.enableKeyboardNav) {
            $(document).keydown(function (event) {
              if (event.keyCode == 39) {
                forcePrevNext("next")
                $(document).unbind("keydown")
              }
              if (event.keyCode == 37) {
                forcePrevNext("prev")
                $(document).unbind("keydown")
              }
              if (event.keyCode == 80 || event.keyCode == 111) forcePause()
              if (event.keyCode == 83 || event.keyCode == 115) {
                forceStart()
                $(document).unbind("keydown")
              }
            })
          }
        }

        function forcePrevNext(dir) {
          o.onPauseClick.call(this)
          $("#btn_rt" + randID).unbind("click")
          $("#btn_lt" + randID).unbind("click")
          setTimeout(function () {
            $("#play_pause_btn" + randID).css("background-position", "0 -16px")
          }, o.transitionSpeed - 1)
          autopilot = 0
          $("#progress" + randID)
            .stop()
            .fadeOut()
          status = "pause"
          clearTimeout(clearInt)
          dir == "prev" ? moveRight() : moveLeft()
          $("#play_pause_btn" + randID).unbind("click")
          setTimeout(function () {
            $("#play_pause_btn" + randID).bind("click", function () {
              forceStart()
            })
            $("#btn_rt" + randID).bind("click", function () {
              forcePrevNext("next")
            })
            $("#btn_lt" + randID).bind("click", function () {
              forcePrevNext("prev")
            })
          }, o.transitionSpeed)
        }

        function forcePause() {
          $("#play_pause_btn" + randID).unbind("click") // unbind the click, wait for transition, then reenable
          if (autopilot) {
            o.onPauseClick.call(this)
            $("#play_pause_btn" + randID)
              .fadeTo(250, 0, function () {
                $(this).css({ "background-position": "0 -16px", opacity: ".5" })
              })
              .animate({ opacity: 0.5 }, 250)
            autopilot = 0
            showminmax()
            $("#progress" + randID)
              .stop()
              .fadeOut()
            clearTimeout(clearInt)
            setTimeout(function () {
              $("#play_pause_btn" + randID).bind("click", function () {
                forceStart()
              })
            }, o.transitionSpeed)
          }
        }

        function forceStart() {
          $("#play_pause_btn" + randID).unbind("click") // unbind the click, wait for transition, then reenable
          if (!autopilot) {
            setTimeout(function () {
              $("#play_pause_btn" + randID).css("background-position", "0 0")
            }, o.transitionSpeed - 1)
            autopilot = 1
            moveLeft()
            clearInt = setInterval(function () {
              moveLeft()
            }, o.displayTime + o.transitionSpeed)
            setTimeout(function () {
              $("#play_pause_btn" + randID).bind("click", function () {
                forcePause()
              })
            }, o.transitionSpeed)
          }
        }

        function preMove() {
          hideCaption()
          // Fade out play/pause/left/right
          if (o.showControls && o.prevNextInternal) {
            $("#play_pause_btn" + randID).fadeOut(200)
            $("#btn_lt" + randID).fadeOut(200)
            $("#btn_rt" + randID).fadeOut(200)
          }
          if (o.displayThumbnails)
            for (i = 1; i <= numImages; i++)
              $("#thumb" + randID + "_" + i)
                .css({ "border-color": "#ccc" })
                .animate({ opacity: 0.65 }, 500)
        }

        function postMove() {
          if (o.showControls && o.prevNextInternal) {
            $("#play_pause_btn" + randID).fadeIn(200)
            $("#btn_lt" + randID).fadeIn(200)
            $("#btn_rt" + randID).fadeIn(200)
          }
          keyBind()
          if (o.autoHideCaptions && isHover) autoShowCap()
          if (o.displayThumbnails)
            for (i = 0; i < viewable.length; i++)
              $("#thumb" + randID + "_" + viewable[i])
                .css({ "border-color": "#ff0000" })
                .animate({ opacity: 1 }, 500)
          if (!o.autoHideCaptions)
            for (i = 1; i <= o.inView; i++)
              showtext($("li:eq(" + i + ") p", obj).html(), i)
          if (o.displayThumbnails)
            $("#thumbs" + randID + " div")
              .unbind("click")
              .bind("click", thumbclick)
              .css({ cursor: "pointer" })
          ary = []
          for (x = 1; x <= o.inView; x++) {
            ary.push($("img:eq(" + x + ")", obj).attr("src"))
          }
          o.onSlideEnd.call(this, ary)
        }

        function moveLeft(dist) {
          if (dist == null) dist = o.advance
          preMove()
          if (o.displayThumbnails) {
            for (i = 1; i <= dist; i++) {
              viewable.push(unviewable.shift())
              unviewable.push(viewable.shift())
            }
          }
          if (o.displayTime == 0) {
            clearInterval(clearInt)
          } // If running a contonuous show with no display time, fist clear the interval. Then below, recursively call moveLeft
          $("li:lt(" + dist + ")", obj)
            .clone(true)
            .insertAfter($("li:last", obj)) // Copy the first image (offscreen to the left) to the end of the list (offscreen to the right)
          o.onSlideStart.call(this, viewable, "left")
          $("ul", obj).animate(
            {
              left:
                -imgWidth * (dist + 1) - parseInt(o.padding) * (dist + 1) * 2,
            },
            o.transitionSpeed,
            o.easeLeft,
            function () {
              // Animate the entire list to the left
              $("li:lt(" + dist + ")", obj).remove() // When the animation finishes, remove the first image (on the left). It has already been copied to the end of the list (right)
              $(this).css({ left: -imgWidth - parseInt(o.padding) * 2 })
              if (o.displayProgressBar && autopilot) startProgressBar()
              postMove()
              if (o.displayTime == 0) {
                moveLeft()
              }
            },
          )
        }
        function moveRight(dist) {
          if (dist == null) dist = o.advance
          preMove()
          if (o.displayThumbnails) {
            for (i = 1; i <= dist; i++) {
              viewable.unshift(unviewable.pop())
              unviewable.unshift(viewable.pop())
            }
          }
          $("li:gt(" + (numImages - (dist + 1)) + ")", obj)
            .clone(true)
            .insertBefore($("li:first", obj)) // Copy rightmost (last) li and insert it after the first li
          o.onSlideStart.call(this, viewable, "right")
          $("ul", obj)
            .css(
              "left",
              -(imgWidth * (dist + 1)) - parseInt(o.padding) * ((dist + 1) * 2),
            )
            .animate(
              { left: -imgWidth - parseInt(o.padding) * 2 },
              o.transitionSpeed,
              o.easeRight,
              function () {
                $("li:gt(" + (numImages - 1) + ")", obj).remove()
                postMove()
              },
            )
        }

        // Kickoff the show
        if (autopilot) {
          var clearInt = setInterval(function () {
            moveLeft()
          }, o.displayTime + o.transitionSpeed)
          if (o.displayProgressBar)
            startProgressBar(o.displayTime + o.transitionSpeed)
        } else {
          status = "pause"
          $("#play_pause_btn" + randID).css({
            "background-position": "0 -16px",
          })
        }
        keyBind()
      })
    },
  })
})(jQuery)
