/* 
 * jQuery.simpleSlider.js
 * © 2011 kumagaiyusuke
*/

$.simpleSlider = function (width, height, contents, transition, direction, reverseMode) {

  if (typeof width === "undefined" || typeof height === "undefined" || typeof transition === "undefined") {
    throw new Error("引数type, width, heightの値は必須です。");
  }
  
  if (!$.isArray(contents)) {
    throw new Error("引数contentsは配列で指定する必要があります。");
  }
  
  var $slider = $("<div>");
  
  var itemList = [];
  var currentItem = 0;
  var timer;
  
  var transitions = $.simpleSlider.transitions;
  var directions = $.simpleSlider.directions;
  var events = $.simpleSlider.events;
  
  var isActiveTransition = false;
  var isActiveDirection = false;
  
  var isAnimated = false;
  
  
  // !初期化
  
  for (key in transitions) {
    if (transitions[key] === transition) {
      isActiveTransition = true;
    }
  }
  
  if (!isActiveTransition) {
    transition = transitions.FADE;
  }
  
  for (key in directions) {
    if (directions[key] === direction) {
      isActiveDirection = true;
    }
  }
  
  if (!isActiveDirection) {
    direction = directions.RIGHT;
  }
  
  $slider.css({
    position: "relative",
    width: width,
    height: height,
    overflow: "hidden"
  });
  
  for (var i = 0; i < contents.length; ++i) {
    addItem(contents[i]);
  }
  
  
  // !プライベート
  
  function addItem(contents) {
    
    var $item = $("<div>", {
      "class": "item"
    });
    
    $item.html(contents);
  
    $item.css({
      position: "absolute",
      top: "-100%",
      left: "-100%",
      width: "100%",
      height: "100%",
      overflow: "hidden"
    });
    
    if (itemList.length < 1) {
      $item.css({
        top: "0%",
        left: "0%"
      });
    }
    
    itemList.push($item);
    
    $slider.append($item);
  };
  
  
  // !パブリック
  
  $slider.getCurrentItem = function () {
    return currentItem;
  };
  
  $slider.getTotalItems = function () {
    return itemList.length;
  };
  
  $slider.slideTo = function (i, duration, easing) {
    
    if (i < 0 || i >= itemList.length) {
      throw new Error("アイテム番号は0から" + (itemList.length - 1) + "の間で指定する必要があります。");
    }
    
    if (currentItem === i || isAnimated) {
      return;
    }
    
    var $current = itemList[currentItem];
    var $next = itemList[i];
    
    var reverse = false;
    
    var data = {
      currentItem: currentItem,
      nextItem: i,
      reverse: reverse
    };
    
    if (reverseMode && i < currentItem) {
      reverse = true;
    }
    
    isAnimated = true;
    
    $slider.trigger(events.SLIDE_START, [data]);

    setTimeout(function () {
      isAnimated = false;
      $slider.trigger(events.SLIDE_END, [data]);
    }, duration);
    
    transition($current, $next, duration, easing, direction, reverse);
    
    currentItem = i;
  };
  
  $slider.slidePrev = function (duration, easing) {
    
    var nextItem = currentItem - 1;
    
    if (nextItem < 0) {
      nextItem = itemList.length - 1;
    }
    
    $slider.slideTo(nextItem, duration, easing);
  };
  
  $slider.slideNext = function (duration, easing) {
    
    var nextItem = currentItem + 1;
    
    if (nextItem >= itemList.length) {
      nextItem = 0;
    }
    
    $slider.slideTo(nextItem, duration, easing);
  };
  
  $slider.resize = function (width, height) {
  
    if (typeof width === "undefined" || typeof height === "undefined") {
      throw new Error("widthとheightの値は必須です。");
    }reverseMode

    $slider.css({
      width: width,
      height: height
    });

  };
  
  return $slider;
};


// !スタティック

$.simpleSlider.events = {
  SLIDE_START: "slideStart",
  SLIDE_END: "slideEnd"
};

$.simpleSlider.directions = {
  TOP: "top",
  RIGHT: "right",
  BOTTOM: "bottom",
  LEFT: "left"
};

$.simpleSlider.transitions = {
  
  FADE: function ($current, $next, duration, easing) {
    
    $current.stop();
    
    $current.css({
      top: "-100%",
      left: "-100%",
      opacity: 1
    });
    
    $next.stop();
    
    $next.css({
      top: 0,
      left: 0,
      opacity: 0
    });
    
    $next.animate({
      opacity: 1
    }, {
      duration: duration,
      easing: easing,
      complete: function () {
        if (!$.support.opacity) {
          this.style.removeAttribute("filter");
        }
      }
    });
  },
  
  CROSSFADE: function ($current, $next, duration, easing) {
    
    $current.stop();
    
    $current.css({
      top: 0,
      left: 0,
      opacity: 1
    });
    
    $current.animate({
      opacity: 0
    }, {
      duration: duration,
      easing: easing,
      complete: function () {
        $(this).css({
          top: "-100%",
          left: "-100%",
          opacity: 1
        });
      }
    });
    
    $next.stop();
    
    $next.css({
      top: 0,
      left: 0,
      opacity: 0
    });
    
    $next.animate({
      opacity: 1
    }, {
      duration: duration,
      easing: easing,
      complete: function () {
        if (!$.support.opacity) {
          this.style.removeAttribute("filter");
        }
      }
    });
  },
  
  MASK: function ($current, $next, duration, easing, direction, reverse) {
    
    var directions = $.simpleSlider.directions;

    var $front, $back, frontInit, frontAnimate, frontAnimateComplete;
    
    if ((direction === directions.RIGHT && !reverse) || (direction === directions.LEFT && reverse)) {

      $front = $next;
      $back  = $current;
      
      frontInit    = { width: "0%" };
      frontAnimate = { width: "100%" };
      
      frontAnimateComplete = function () {
        $back.css({
          top: "-100%",
          left: "-100%"
        });
      }
    }
    else if ((direction === directions.RIGHT && reverse) || (direction === directions.LEFT && !reverse)) {

      $front = $current;
      $back  = $next;
      
      frontInit    = { width: "100%" };
      frontAnimate = { width: "0%" };
      
      frontAnimateComplete = function () {
        $front.css({
          top: "-100%",
          left: "-100%",
          width: "100%"
        });
      }
    }
    else if ((direction === directions.TOP && !reverse) || (direction === directions.BOTTOM && reverse)) {

      $front = $current;
      $back  = $next;
      
      frontInit = { height: "100%" };
      frontAnimate = { height: "0%" };
      
      frontAnimateComplete = function () {
        $front.css({
          top: "-100%",
          left: "-100%",
          height: "100%"
        });
      }
    }
    else if ((direction === directions.TOP && reverse) || (direction === directions.BOTTOM && !reverse)) {

      $front = $next;
      $back = $current;
      
      frontInit = { height: "0%" };
      frontAnimate = { height: "100%" };
      
      frontAnimateComplete = function () {
        $back.css({
          top: "-100%",
          left: "-100%"
        });
      }
    }
    
    $current.stop();
    $next.stop();

    $front.css({
      top: 0,
      left: 0,
      zIndex: 2
    });
    
    $back.css({
      top: 0,
      left: 0,
      zIndex: 1
    });
    
    $front.css(frontInit);

    $front.animate(frontAnimate, {
      duration: duration,
      easing: easing,
      complete: frontAnimateComplete
    });

  },
  
  SLIDE: function ($current, $next, duration, easing, direction, reverse) {
    
    var directions = $.simpleSlider.directions;
    var currentAnimate, nextInit, nextAnimate;
  
    $current.stop();
    $next.stop();

    if ((direction === directions.RIGHT && !reverse) || (direction === directions.LEFT && reverse)) {
      currentAnimate = {
        left: "100%"
      };
      nextInit = {
        top: "0%",
        left: "-100%"
      };
      nextAnimate = {
        left: "0%"
      };
    }
    else if ((direction === directions.RIGHT && reverse) || (direction === directions.LEFT && !reverse)) {
      currentAnimate = {
        left: "-100%"
      };
      nextInit = {
        top: "0%",
        left: "100%"
      };
      nextAnimate = {
        left: "0%"
      };
    }
    else if ((direction === directions.TOP && !reverse) || (direction === directions.BOTTOM && reverse)) {
    
      currentAnimate = {
        top: "-100%"
      };
      nextInit = {
        top: "100%",
        left: "0"
      };
      nextAnimate = {
        top: "0"
      };
    }
    else if ((direction === directions.TOP && reverse) || (direction === directions.BOTTOM && !reverse)) {
      currentAnimate = {
        top: "100%"
      };
      nextInit = {
        top: "-100%",
        left: "0"
      };
      nextAnimate = {
        top: "0"
      };
    }
      
    $current.animate(currentAnimate, {
      duration: duration,
      easing: easing,
      complete: function () {
        $current.css({
          top: "-100%",
          left: "-100%"
        });
      }
    });

    $next.css(nextInit);

    $next.animate(nextAnimate, {
      duration: duration,
      easing: easing
    });
  }
};

