/*!
 * jQuery.bgSwitcher
 *
 * @version    0.2.7-beta
 * @author     Hiroshi Hoaki <rewish.org@gmail.com>
 * @copyright  2010-2011 Hiroshi Hoaki
 * @license    http://rewish.org/license/mit The MIT License
 * @link       http://rewish.org/javascript/jquery_bg_switcher
 */
(function($) {

	$.fn.bgSwitcher = function(options) {
		return this.each(function() {
			$(this).data('bgSwitcher', new $.bgSwitcher(this, options));
		});
	};

	$.bgSwitcher = function(node, options) {
		this.node = $(node);
		this.setOptions(options);
		this.initialize();
	};

	$.bgSwitcher.defaultOptions = {
		images   : null,
		copyCss : null,
		interval : 5000,
		autoStart: true,
		fadeSpeed: 1000,
		loop     : true,
		random   : false,
		startRandom: false,
		resize   : false,
		navi     : null,
		copy	: null,
		callback : function(){}
	};

	$.bgSwitcher.prototype = {

		setOptions: function(options) {
			this.options = $.extend(true, {}, $.bgSwitcher.defaultOptions, options);

			if (!(this.options.images instanceof Array) ||
			!(this.options.copyCss instanceof Array)) {
				throw new Error('options.images is invalid.');
			}

			if (typeof this.options.images[0] === 'string'
					&& typeof this.options.images[1] === 'number'
					&& typeof this.options.images[2] === 'number') {
				this.sequence();
			}


			if (this.options.images.length <= 1) {
				throw new Error('Image must be at least more than two.');
			}
		},

		initialize: function() {
			this.preload();

			
			
			
			if(this.options.startRandom){
				// 開始位置のランダム化
				var length = this.options.images.length;
				this.index = Math.floor(Math.random() * length);
			
			}else{
				this.index = -1;
			}
			
			this.next  = this.options.random ? this.random : this.order;
			this.next();
			this.normalSwitch(this.options.images[this.index]);

			if (this.options.fadeSpeed > 0) {
				this.initFadeNode();
				this.doSwitch = this.fadeSwitch;
			} else {
				this.doSwitch = this.normalSwitch;
			}

			if (this.options.autoStart) {
				this.start();
			}

			if (this.options.resize) {
				$(window).bind('resize.bgSwitcher', $.proxy(this.resizeHandler, this));
			}
		},

		start: function() {
			if (this.timeId) {
				return;
			}
			var self = this;
			this.timeId = setInterval(function() {
				self.next();
				self.doSwitch(self.options.images[self.index]);
			}, self.options.interval);
		},

		stop: function() {
			if (this.timeId) {
				clearInterval(this.timeId);
				this.timeId = null;
			}
		},

		toggle: function() {
			if (this.timeId) {
				this.stop();
			} else {
				this.start();
			}
		},

		reset: function() {
			this.index = 0;
			this.stop();
			this.doSwitch(this.options.images[this.index]);
			this.start();
		},

		order: function() {
			var length = this.options.images.length;
			++this.index;
			if (this.index === length) {
				this.index = 0;
			}
			if (!this.options.loop && this.index >= length - 1) {
				this.stop();
			}
		},

		random: function() {
			var length = this.options.images.length,
			    index  = this.index;
			while (this.index === index) {
				index = Math.floor(Math.random() * length);
			}
			this.index = index;
		},

		sequence: function() {
			var tmp  = [],
			    base = this.options.images[0],
			    min  = this.options.images[1],
			    max  = this.options.images[2];
			do {
				tmp.push(base.replace(/\.\w+$/, min + '$&'));
			} while (++min <= max);
			this.options.images = tmp;
			
		},


		preload: function() {
			this.loadedImages = [];
			for (var i = 0, len = this.options.images.length; i < len; ++i) {
				this.loadedImages[i] = new Image;
				this.loadedImages[i].src = this.options.images[i];
			}
		},

		initFadeNode: function() {
			
			this.clickCount = 0;
			this.playing = false;
			
			var tagName = this.node[0].tagName.toLowerCase();

			if (tagName === 'html') {
				throw new Error('FadeOut the HTML not allowed.');
			}

			if (tagName === 'body') {
				this.initRootNode();
				tagName = 'div';
			}

			var zIndex = this.node.css('zIndex'),
			    offset = this.node.offset();

			if (isNaN(zIndex)) {
				zIndex = 1000;
				this.node.css({zIndex: zIndex});
			}

			this.fadeNode = $('<'+ tagName +'>');
			this.fadeNode.css({
				display: 'block',
				position: 'absolute',
				zIndex: zIndex - 1,
				top: offset.top,
				left: offset.left,
//top: 0,
//left: 0,
				width: this.node.innerWidth(),
				height: this.node.innerHeight(),
				backgroundImage: this.node.css('backgroundImage'),
				/* IE9の場合、background-position-x/yを
					background-imageで一括して指定すると
					なぜかbackgroundPositionには0% 0%が設定されてしまうため、
					backgroundPositionX/Yを個別に取り出すように修正 */
				/*
				backgroundPosition: this.node.css('backgroundPosition') || [
					this.node.css('backgroundPositionX'),
					this.node.css('backgroundPositionY')
				].join(' '),
				*/
				backgroundPosition:(this.node.css('backgroundPositionX') && this.node.css('backgroundPositionX')) ?
					[this.node.css('backgroundPositionX'), this.node.css('backgroundPositionY')].join(' ') :
					this.node.css('backgroundPosition'),
				
				backgroundRepeat: this.node.css('backgroundRepeat'),
				backgroundColor: this.node.css('backgroundColor'),
				backgroundAttachment: this.node.css('backgroundAttachment')
			});

			this.origNode = this.node;
			this.origNode.css({
				position: 'relative',
				background: 'none'
			});

			this.node = this.fadeNode.clone();
			this.node.css('zIndex', zIndex - 2);

			this.origNode.after(this.fadeNode, this.node);

			this.node.hide();
			this.fadeNode.hide();
			this.node.fadeIn(this.options.fadeSpeed);
		},

		initRootNode: function() {
			
			var id = 'bgSwitcher-' + (+new Date);

			$('> *', this.node).not('script').wrapAll('<div id="'+ id +'">');

			var rootNode = $('#' + id),
			    bodyNode = this.node;

			var styles = {
				backgroundImage: bodyNode.css('backgroundImage'),
				backgroundPosition: bodyNode.css('backgroundPosition') || [
					bodyNode.css('backgroundPositionX'),
					bodyNode.css('backgroundPositionY')
				].join(' '),
				backgroundRepeat: bodyNode.css('backgroundRepeat'),
				backgroundColor: bodyNode.css('backgroundColor'),
				backgroundAttachment: bodyNode.css('backgroundAttachment')
			};
			var edge = ['Top', 'Bottom', 'Right', 'Left'];
			for (var i = 0; i < 4; ++i) {
				var property = 'padding' + edge[i];
				styles[property]  = +bodyNode.css('margin' + edge[i]).replace(/\D/g, '');
				styles[property] += +bodyNode.css('padding' + edge[i]).replace(/\D/g, '');
				styles[property] += 'px';
			}
			rootNode.css(styles);

			bodyNode.css({
				margin: 0,
				padding: 0,
				background: 'none'
			});
				

			this.node = rootNode;

			// Observe resize event
			this.options.resize = true;
		},

		resizeHandler: function() {
			var width = this.origNode.innerWidth();
			this.node.width(width);
			this.fadeNode.width(width);
		},

		normalSwitch: function(imageUrl) {
			this.node.css('backgroundImage', 'url('+ imageUrl +')');
			this.setCopy(0);	
			this.setNavi();
		},

		fadeSwitch: function(imageUrl) {

			if(this.playing){
				this.clickCount++;
			}
			if(this.clickCount >= 1){
				return;
			}
			this.playing = true;
						
			var self = this;
			this.fadeNode.stop(true, true);
			this.fadeNode.css('backgroundImage', this.node.css('backgroundImage'));
			this.fadeNode.show(0, function() {
/*
				self.node.css('backgroundImage', 'url('+ imageUrl +')');
				self.fadeNode.fadeOut(self.options.fadeSpeed);
*/
			
				self.node.hide();
				self.node.css('backgroundImage', 'url('+ imageUrl +')');
				self.node.fadeIn(self.options.fadeSpeed);
				self.fadeNode.fadeOut(self.options.fadeSpeed, function(){
					self.playing = false;
					self.clickCount = 0;
				});
				
				self.setCopy(self.options.fadeSpeed*0.5);			
				self.setNavi();
				
			});
		},
			
		setCopy: function(speed){
			var self = this;
			if(this.options.copy){
				var no = self.index;
				
				if(self.options.copyCss.length > self.index){

					var nextCss = $(self.options.copyCss[self.index]);
					
					if(isIE(6)){
						
						if(self.currCss){
							self.currCss.css("top", "9999px");
						}
			
						nextCss.css("top", "0");
						self.currCss = nextCss;
						
					}else{
						nextCss.hide().css("top", 0);
						
						var prevIndex = self.index - 2;
						if(prevIndex < 0){
							prevIndex = prevIndex + self.options.copyCss.length;
						}
						// アニメーションの途中に移動されたときのために
						// アニメーション中の要素のアニメーションをキャンセルする
						var prevCss = $(self.options.copyCss[prevIndex]);
						prevCss.stop().fadeOut(0.0);
						
						if(self.currCss){
							self.currCss.stop().fadeIn(0.0).fadeOut(speed, function(){
								nextCss.fadeIn(speed);
								
							});
							self.currCss = nextCss;
						}else{
							
							nextCss.fadeIn(speed);
							self.currCss = nextCss;
						}
			
					}	
				
				}
			}
			
			
			function isIE(ver)
			{
				switch (ver) {
					case 6:
						return (! jQuery.support.style && typeof document.documentElement.style.maxHeight == "undefined");
					case 7:
						return (! jQuery.support.style && typeof document.documentElement.style.maxHeight != "undefined");
					case 8:
						return (! jQuery.support.opacity && jQuery.support.style);
					case 9:
						return (window.ActiveXObject != undefined && jQuery.support.opacity);
					case 67:
						return (! jQuery.support.style);
					case 678:
						return (! jQuery.support.opacity);
					default:
						return (window.ActiveXObject != undefined);
				}
			};
		},

		setNavi: function() {
			var self = this;
			if(self.options.navi){
				no = self.index;
				$(self.options.navi).each(function(idx){
					$(this).attr('src',$(this).attr('src').replace('_on',''));
					if(no == idx){

						$(this).attr('src',$(this).attr('src').replace('.png','_on.png'));
					
					}
				});
			}
		}

	};

})(jQuery);

