/**
 * jq.slideViewer.js
 * @see jquery.js
 */

/**
 * [$.scope] on jQuery
 */
jQuery.scope = function(t, f) {
	return function() {
		return f.apply(t, arguments);
	}
};

/**
 * easing plugin on jQuery
 */
jQuery.extend(jQuery.easing, {
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	}
});

/**
 * slideViewerClass
 */
function slideViewerClass() {
    this.initialize.apply(this, arguments);
};

slideViewerClass.prototype = {

	/**
	 * initialize
	 */
	initialize : function() {
		this._tmp = {};
		this._sInf = {};
		this._vInf = {};
		this._conf = {
			slider: 'div.j-ibox',
			viewer: 'p.image',
			thumbW: 120, // padding, border included.
			thumbMargin: 5,
			next: 'Next',
			prev: 'Prev'
		};
	},

	/**
	 * add
	 */
	add : function(f) {
		if(!f) {
			$(this._conf.slider).hide();
			this.prepare();
			return;
		}
		$(this._conf.slider).fadeIn(1500);
		this.addSlider();
		this.addViewer();
		this.addEvent();
	},

	/**
	 * getPadding
	 */
	getPadding : function(t) {
		var padding = {
			top: parseInt($(t).css('paddingTop').replace(/px|em|pt/, '')),
			right: parseInt($(t).css('paddingRight').replace(/px|em|pt/, '')),
			bottom: parseInt($(t).css('paddingBottom').replace(/px|em|pt/, '')),
			left: parseInt($(t).css('paddingLeft').replace(/px|em|pt/, ''))
		};
		return padding;
	},

	/**
	 * addSlider
	 */
	addSlider : function() {
		// アイテム内の表示サイズ
		$(this._conf.slider).append('<div class="sl-inner"><div class="sl-tmp">&nbsp;</div></div>'); // tmp
		var padding = this.getPadding('div.sl-tmp');
		this._sInf.margin = {
			h: $('div.sl-tmp').outerHeight() - $('div.sl-tmp').innerHeight() + padding.top + padding.bottom,
			w: $('div.sl-tmp').outerWidth() - $('div.sl-tmp').innerWidth() + padding.right + padding.left
		};

		// イメージサイズ
		this._sInf.imgsize = {
			h: 0,
			w: this._conf.thumbW - this._sInf.margin.w
		};
		// スライダー内の表示幅
		var slpadding = this.getPadding(this._conf.slider);
		this._sInf.slWidth = $(this._conf.slider).innerWidth() - slpadding.right - slpadding.left;

		this._tmp.doc = '';
		$(this._conf.slider + ' > img').each(
			$.scope(this, function(i, e){
				var src = $(e).attr('src');
				var alt = $(e).attr('alt');
				var h = Math.round($(e).height() * this._sInf.imgsize.w / $(e).width());
				if(this._sInf.imgsize.h < h) this._sInf.imgsize.h = h; // イメージサイズ高さ更新
				this._tmp.doc += [
					'<div>',
					'<img src="' +src+ '" alt="' +alt+ '" style="width:' +this._sInf.imgsize.w+ 'px;height:' +h+ 'px;" />', // image size added
					'<span>' +alt+ '</span>',
					'</div>'
				].join('');
			})
		);
		$(this._conf.slider).html('<div class="sl-inner">' +this._tmp.doc+ '</div>');
		$('div.slinner > div > span').hide();
		this._tmp.doc = '';

		// イメージ総数
		this._sInf.rows = $('div.sl-inner > div').length;

		// 表示数
		this._sInf.viewNum = Math.floor(
			this._sInf.slWidth / (this._conf.thumbW + this._conf.thumbMargin)
		);

		// アイテム間のマージン
		this._sInf.i2i = Math.floor(
			(this._sInf.slWidth - this._conf.thumbW * this._sInf.viewNum) / (this._sInf.viewNum - 1)
		);

		// img fixed css
		$('div.sl-inner > div > img').each(function(i, e) {
			$(e).css({
				display: 'block',
				position: 'absolute',
				top: '50%',
				left: '50%',
				border: 'none',
				marginTop: '-' + ($(e).height() / 2) + 'px',
				marginLeft: '-' + ($(e).width() / 2) + 'px'
			});
		});

		// items fixed css
		$('div.sl-inner > div').css({
			position: 'relative',
			float: 'left',
			marginRight: this._sInf.i2i + 'px',
			cursor: 'pointer',
			// IE6...
			width: this._sInf.imgsize.w + 'px',
			height: this._sInf.imgsize.h + 'px'
		});

		// inner fixed css
		$('div.sl-inner').css({
			width: (this._conf.thumbW + this._sInf.i2i) * this._sInf.rows + 'px',
			height: $('div.sl-inner > div:eq(0)').outerHeight() + 'px',
			position: 'relative',
			padding: '0',
			margin: '0',
			border: 'none',
			overflow: 'hidden',
			position: 'relative'
		});

		// outer fixed css
		$(this._conf.slider).css({
			overflow: 'hidden',
			position: 'relative'
		});

		this.addAllow();
	},

	/**
	 * addViewer
	 */
	addViewer : function() {
		$(this._conf.viewer).html('<div class="vl-inner">' + $('div.sl-inner').html() + '</div>');
		$('div.vlinner > div > span').hide();

		this._vInf.height = 0;
		this._vInf.width = 0;
		// reset img
		$('div.vl-inner > div > img').each(
			$.scope(this, function(i, e) {
				$(e).removeAttr('style');
				if(this._vInf.height < $(e).height()) this._vInf.height = $(e).height();
				if(this._vInf.width < $(e).width()) this._vInf.width = $(e).width();
			})
		);

		// items
		$('div.vl-inner > div').css({
			margin: '0',
			width: this._vInf.width + 'px',
			height: this._vInf.height + 'px',
			float: 'left',
			cursor: 'default'
		});

		// img
		$('div.vl-inner > div > img').each(function(i, e) {
				$(e).css({
					display: 'block',
					position: 'absolute',
					top: '50%',
					left: '50%',
					marginTop: '-' +Math.floor($(e).height() / 2)+ 'px',
					marginLeft: '-' +Math.floor($(e).width() / 2)+ 'px',
					border: 'none'
				});
		});

		// inner
		$('div.vl-inner').css({
			width: $('div.vl-inner > div:eq(0)').outerWidth() * this._sInf.rows + 'px',
			margin: '0',
			padding: '0',
			position: 'relative'
		});

		// outer
		$(this._conf.viewer).css({
			overflow: 'hidden',
			position: 'relative',
			width: $('div.vl-inner > div:eq(0)').outerWidth() + 'px',
			height: $('div.vl-inner > div:eq(0)').outerHeight() + 'px'
		});

		this.addFrame();
	},

	/**
	 * addFrame
	 */
	addFrame: function() {
		$('div.sl-inner').append('<div class="sl-current"></div>');
		$('div.sl-current').css({
			width: $('div.sl-inner > div:eq(0)').outerWidth() - 3*2 + 'px',
			height: $('div.sl-inner > div:eq(0)').outerHeight() - 3*2 + 'px',
			position: 'absolute',
			top: $('div.sl-inner > div:eq(0)').position().top + 'px',
			left: $('div.sl-inner > div:eq(0)').position().left + 'px',
			border: '3px solid gold',
			background: 'none',
			padding: '0',
			margin: '0'
		});
	},

	/**
	 * addAllow
	 */
	addAllow : function() {
		var doc = [
			'<a href="javascript:void(0);" title="Next" class="sl-next">' +this._conf.next+ '</a>',
			'<a href="javascript:void(0);" title="Prev" class="sl-prev">' +this._conf.prev+ '</a>'
		].join('');
		$(this._conf.slider).append(doc);

		$('a.sl-next,a.sl-prev').css({
			display: 'block',
			position: 'absolute',
			top: '50%',
			zIndex: '999'
		});

		var mT = Math.floor($('a.sl-next').outerHeight() / 2);
		$('a.sl-next').css({
			marginTop: '-' +mT+ 'px',
			right: '0px'
		});
		$('a.sl-prev').css({
			marginTop: '-' +mT+ 'px',
			left: '0px'
		});
		this.buttonStatus();
	},

	/**
	 * addEvent
	 */
	addEvent : function() {
		// view
		$('div.sl-inner > div').each(function(i, e) {
			$(e).click(function() {
				var i = $('div.sl-inner > div').index(this);
				var w = $('div.vl-inner > div:eq(' +i+ ')').outerWidth();
				var m = $('div.vl-inner').position().left - (w * i * -1);
				$('div.vl-inner').animate({left: '-=' +m+ 'px'}, 'slow', 'easeInOutExpo');
				$('div.sl-current').animate({left: $(this).position().left + 'px'}, 'slow', 'easeInOutExpo');
			});
			$(e).hover(
				function() {
					$(this).css({
						filter: 'alpha(opacity=80)',
						MozOpacity: '0.8',
						opacity: '0.8'
					});
				},
				function() {
					$(this).css({
						filter: 'alpha(opacity=100)',
						MozOpacity: '1.00',
						opacity: '1.00'
					});
				}
			);
		});

		// move right
		$('a.sl-next').click(
			$.scope(this, function(){
				var a = Math.abs($('div.sl-inner').position().left);
				var m = (this._conf.thumbW + this._sInf.i2i) * this._sInf.viewNum;
				var l = (this._conf.thumbW + this._sInf.i2i) * (this._sInf.rows - this._sInf.viewNum);
				if(a + m > l) m = l - a;
				$('div.sl-inner').animate({left: '-=' +m+ 'px'}, 'slow', 'easeInOutExpo');
				this.buttonStatus();
			})
		);

		// move left
		$('a.sl-prev').click(
			$.scope(this, function(){
				var a = Math.abs($('div.sl-inner').position().left);
				var m = (this._conf.thumbW + this._sInf.i2i) * this._sInf.viewNum;
				if(a - m < 0) m = a;
				$('div.sl-inner').animate({left: '+=' +m+ 'px'}, 'slow', 'swing');
				this.buttonStatus();
			})
		);

		// current
		$('div.sl-current').unbind();
	},

	buttonStatus : function(r) {
		if(!r) {
			var tm = setTimeout($.scope(this, function() {this.buttonStatus(true);}), 800);
			return;
		}
		var a = Math.abs($('div.sl-inner').position().left);
		var l = (this._conf.thumbW + this._sInf.i2i) * (this._sInf.rows - this._sInf.viewNum);
		if(a >= l) {
			$('a.sl-next').hide();
		} else {
			$('a.sl-next').show();
		}
		if(a <= 0) {
			$('a.sl-prev').hide();
		} else {
			$('a.sl-prev').show();
		}
	},

	/**
	 * prepare
	 */
	prepare : function() {
		if(!this._tmp.length) {
			$(this._conf.slider + ' > img').each(
				$.scope(this, function(i, e){
					this._tmp[i] = { obj: new Image() };
					this._tmp[i].obj.src = $(e).attr('src');
				})
			);
		}
		for(var i in this._tmp) {
			if(!this._tmp[i].obj.complete) var p = true;
		}
		if(!p) {
			this._tmp = {};
			this.add(true);
			return;
		}
		var tm = setTimeout($.scope(this, this.prepare), 120);
	}
}

