(
  function($) {
    function initCarouselLite (elem, options) {
      return elem.each(
        function() {
          var
            elem = this,
            div = $(elem),
            ul = $("ul", div),
            li = $("li", ul),
            itemLength = li.size(),
            v = options.visible,
            inv = itemLength-v,
            animCss = options.vertical ? "top" : "left",
            sizeCss = options.vertical ? "height" :"width";
          elem.options = options;
          elem.currentSlide = options.start;
          if (options.circular) {
            ul.prepend(li.slice(v).clone(true));
            ul.append(li.slice(0,v).clone(true));
            elem.currentSlide += inv;
            li = $("li", ul),
            itemLength = li.size();
            inv = itemLength-v;
          }
          elem.futureCurrentSlide = elem.currentSlide + options.scroll;
          if (options.autoLayout) {
            div.css("visibility", "visible");
            li.css({
              overflow: "hidden",
              float: options.vertical ? "none" : "left"
            });
            ul.css({
              margin: "0",
              padding: "0",
              position: "relative",
              "list-style-type": "none",
              "z-index": "1"
            });
            div.css({
              overflow: "hidden",
              position: "relative",
              "z-index": "2",
              left: "0px"
            });
            li.css({
              width: li.width(),
              height: li.height()
            });
            div.css(sizeCss, sliceSize(options, li, v));
            ul.css(sizeCss, totalSize(options, li, itemLength));
          }
          ul.css(animCss, (-sliceSize(options, li, elem.currentSlide))+"px");
          if (options.btnPrev) {
            $(options.btnPrev).click(
              function() {
                return go(elem.currentSlide-options.scroll, elem);
              }
            );
          }
          if (options.btnNext) {
            $(options.btnNext).click(
              function() {
                return go(elem.currentSlide+options.scroll, elem);
              }
            );
          }
          if (options.btnGo) {
            $.each(
              options.btnGo,
              function(i, val) {
                $(val).click(
                  function() {
                    return go(options.circular ? options.visible+i : i, elem);
                  }
                );
              }
            );
          }
          if (options.mouseWheel && div.mousewheel) {
            div.mousewheel(
              function(e, d) {
                return d>0 ? go(elem.currentSlide-options.scroll, elem) : go(elem.currentSlide+options.scroll, elem);
              }
            ); 
          }          
        }
      );
    }
    
    $.fn.jCarouselLite = function(action, options) {
      if (typeof (action) === 'object') {
        options = action;
        action = "auto";
      }
      switch (action) {
        case "auto": 
        case "create": {
          var defaults = {
              btnPrev: null,
              btnNext: null,
              btnGo: null,
              mouseWheel: false,
              auto: null,
              autoLayout: true,
              startDelay: null,
              speed: 200,
              speedPxps: null,
              easing: null,
              vertical: false,
              circular: true,
              visible: 3,
              start: 0,
              scroll: 1,
              beforeStart: null,
              afterEnd: null
          };
          if (!options) {
            options = {};
          }
          options = $.extend(defaults, options);
          var ret = initCarouselLite(this, options);
          break;
        }
        case "options": {
          var ret = this.each(
            function() {
              if (!options) {
                options = {};
              }
              if (options.scroll) {                
                this.futureCurrentSlide = this.futureCurrentSlide - this.options.scroll + options.scroll;
              }
              this.options = $.extend(this.options, options);
              $(this).children('ul').stop();
              clearTimeout(this.vartimer);
            }
          );
          break;
        }
        case "goto": {
          var ret = this.each(
            function() {
              var
                elem = this,
                ul = $("ul", elem),
                li = $("li", ul),
                itemLength = li.size(),
                orig = itemLength/2;
              if (!options) {
                options = {};
              }
              this.options = $.extend(this.options, options);
              if (this.options.absolutetarget !== undefined) {                
                this.futureCurrentSlide = this.options.absolutetarget;
                this.options.absolutetarget = undefined;
              }
              else if (this.options.target !== undefined) {                
                this.futureCurrentSlide = this.options.target + orig - this.options.visible;
                this.options.target = undefined;
              }
              $(this).children('ul').stop();
              clearTimeout(this.vartimer);
            }
          );
          break;
        }
        case "start": {
          var ret = this.each(
            function() {
              if (!options) {
                options = {};
              }
              this.options = $.extend(this.options, options);
              $(this).children('ul').stop();
              clearTimeout(this.vartimer);
            }
          );
          break;
        }
        case "stop": {
          var ret = this.each(
            function() {
              if (!options) {
                options = {};
              }
              this.options = $.extend(this.options, options);
            }
          );
          break;
        }
        default: {
          var ret = this;
        }
      }
      switch (action) {
        case "auto": 
        case "goto": 
        case "options": 
        case "start": {
          return ret.each(
            function() {
              var
                elem = this,
                options = null;
                widths = new Array,
                ul = $("ul", elem),
                li = $("li", ul),
                itemLength = li.size(),
                orig = itemLength/2,
                animCss = elem.options.vertical ? "top" : "left",
                actualPos = (animCss == "left") ? ul.offset().left-ul.parent().offset().left : ul.offset().top-ul.parent().offset().top,
                c = 0,
                total = -actualPos;
              $("li", elem).each(
                function(i) {
                  total = total - (elem.options.vertical ? $(this).height() : $(this).width());
                  c = i;
                  if (total <= 0) {
                    return false;
                  }
                }
              );
              elem.currentSlide = c;
              var a=0;
              options = elem.options;
              if (options.auto) {
                var startDelay;
                if (options.startDelay === null) {
                  startDelay = options.auto+options.speed;
                }
                else if (options.startDelay < 0) {
                  startDelay = 0;
                }
                else {
                  startDelay = options.startDelay;
                }
                clearTimeout(elem.vartimer);
                elem.vartimer = setTimeout(
                  function() {
                    go(elem.futureCurrentSlide, elem);
                  },
                  startDelay
                );
              }
            }
          );
          break;
        }
        case "stop": {
          return ret.each(
            function() {
              $(this).children('ul').stop();
              clearTimeout(this.vartimer);
            }
          );
          break;
        }
        default: {
          return ret;
        }
      }
    };

    function sliceSize(options, li, n) {
      var result = 0;
      li.slice(0, n).each(
        function() {
          result += options.vertical ? $(this).height() : $(this).width();
        }
      );
      return result;
    }
    
    function totalSize(options, li, n) {
      var result = 0;
      li.each(
        function() {
          result += options.vertical ? $(this).height() : $(this).width();
        }
      );
      return result;
    }
    
    function go(to, elem) {      
      var
        options = null;
      options = elem.options;
      var
        div = $(elem),
        ul = $("ul", div),
        li = $("li", ul),
        itemLength = li.size(),
        v = options.visible,
        inv = itemLength-v,
        orig = itemLength/2,
        animCss = options.vertical ? "top" : "left";
      function vis() {
        return li.slice(elem.currentSlide).slice(0,v);
      };
      if (options.beforeStart) {
        options.beforeStart.call(elem, vis());
      }
      if (options.circular) {
        if (to<0 || to>inv) {
          var 
            offset_pos = (to<0) ? orig : -orig,
            actualPos = (animCss == "left") ? ul.offset().left-ul.parent().offset().left : ul.offset().top-ul.parent().offset().top,
            virtualPos = -sliceSize(options, li, elem.currentSlide),
            destPos = -sliceSize(options, li, elem.currentSlide+offset_pos),
            newPos = destPos + (actualPos-virtualPos);
          ul.css(animCss, newPos+"px");
          to = to + offset_pos;
        } 
      }
      else {
        if (to<0 || to>inv) {
          return;
        }
        else {
        }
      }
      var
        newPos = -sliceSize(options, li, to),
        speed = null,
        currPos = (animCss == "left") ? ul.offset().left-ul.parent().offset().left : ul.offset().top-ul.parent().offset().top;
      if (options.speedPxps === null) {
        speed = options.speed;
      }
      else {
        speed = (Math.abs(newPos-currPos)/options.speedPxps)*1000;
      }
      elem.futureCurrentSlide = to; 
      ul.animate(
        animCss == "left" ? {left: newPos} : {top: newPos},
        speed,
        options.easing,
        function() {
          if (options.afterEnd) {
            options.afterEnd.call(this, vis());
          }
          if (options.auto) {
            clearTimeout(elem.vartimer);
            elem.vartimer = setTimeout(
              function() {
                elem.currentSlide = elem.futureCurrentSlide; 
                elem.futureCurrentSlide = elem.currentSlide+options.scroll;
                go(elem.futureCurrentSlide, elem);
              },
              options.auto
            );                  
          }
        }
      );
      if (!options.circular) {
        $(options.btnPrev + "," + options.btnNext).removeClass("disabled");
        $((elem.currentSlide-options.scroll<0 && options.btnPrev) || (elem.currentSlide+options.scroll > inv && options.btnNext) || []).addClass("disabled");
      }
      return false;
    };
  }
)(jQuery);
