/* ローテーションバナー */

var oriTopSlide = oriTopSlide || {};

oriTopSlide.CONF = {
	ROTATION_INTERVAL: 4000, // 自動ローテーションの間隔(ミリ秒)
	
	BUTTON_CURRENT_BG_SRC: 'http://www.omiya-gyoza.jp/user_data/packages/20111013pc/img/rotation/rotation_arrow.gif',
	BUTTON_NORMAL_BG_SRC: 'http://www.omiya-gyoza.jp/user_data/packages/20111013pc/img/rotation/rotation_arrow_active.gif',
	BUTTON_HEIGHT: 88,
	SLIDES_ID: '#rotation-images',
	BUTTONS_ID: '#rotation-buttons'
};

oriTopSlide.start = function() {
	var model   = new oriTopSlide.Model();
	var slides  = new oriTopSlide.Slides(model, $(oriTopSlide.CONF.SLIDES_ID));
	var buttons = new oriTopSlide.Buttons(model, $(oriTopSlide.CONF.BUTTONS_ID));
	var rotator = new oriTopSlide.Rotator(model, oriTopSlide.CONF.ROTATION_INTERVAL);
	rotator.start();
};

$(function() {
	oriTopSlide.start();
});


/* モデル。
 * 各パーツが知るべき情報を集約して、
 * 変更があった場合に各パーツに通知する。
 */
oriTopSlide.Model = function() {
	this.currentIndex = 0;
	this.numElements = 0;
	this.shouldRotate = true;
};

oriTopSlide.Model.prototype = {
	updateIndex: function(value) {
		if(value < 0) {
			value = this.numElements - 1;
		}
		else if (value >= this.numElements) {
			value = 0;
		}
		
		this.currentIndex = value;
		this._notifyChange();
	},
	
	setShouldRotate: function(value) {
		this.shouldRotate = value;
		this._notifyChange();
	},
	
	_notifyChange: function() {
		$(this).change();
	}
};


/* メイン画像切り替え部
 * ModelのcurrentIndexが変更されるたびに、
 * 対応する画像をフェードで表示する。
 */
oriTopSlide.Slides = function(model, container) {
	this.model = model;
	this.container = container;
	this.elements = $(container).children();
	this.currentElement = null;
	this._currentIndex = -1;
	
	this.init();
	this.update();
};

oriTopSlide.Slides.prototype = {
	init: function() {
		var self = this;
		
		this._initElements();
		
		$(this.container).mouseover(function() {
			self.model.setShouldRotate(false);
		});
		
		$(this.container).mouseout(function() {
			self.model.setShouldRotate(true);
		});
		
		this.model.numElements = this.elements.length;
		
		$(this.model).change(function() {
			self.update();
		});
	},
	
	_initElements: function() {
		$(this.container).css('position', 'relative');
		
		$(this.elements).each(function() {
			$(this).css('position', 'absolute');
			$(this).hide();
		});
	},
	
	update: function() {
		if(this.model.currentIndex == this._currentIndex) {
			return;
		}
		
		this._currentIndex = this.model.currentIndex;
		
		if(this.currentElement) {
			$(this.currentElement).stop();
			$(this.currentElement).fadeTo(200, 0);
			$(this.currentElement).css('z-index', 0);
		}
		
		this.currentElement = this.elements[this._currentIndex];
		$(this.currentElement).queue([]);
		$(this.currentElement).stop();
		$(this.currentElement).fadeTo(200, 1);
		$(this.currentElement).css('z-index', 1);
	}
};


/*
 * ボタン部のクラス。
 * 与えられたHTMLElementをもとにHTMLStringに分解して、
 * スクロールごとにコンテナ内のHTMLを再構成している。
 * ボタンがクリックされた際にはModelのcurrentIndex値を更新する。
 */
oriTopSlide.Buttons = function(model, container, rotator) {
	this.model = model;
	this.container = container;
	
	this.elementHTMLList = [];
	var self = this;
	$(this.container).children().each(function() {
		self.elementHTMLList.push('<li>' + $(this).html() + '</li>');
	});
	this.numElements = this.elementHTMLList.length;
	this._currentIndex = -1;
	
	this.init();
};

oriTopSlide.Buttons.prototype = {
	// 定数へのショートカット
	BUTTON_HEIGHT: oriTopSlide.CONF.BUTTON_HEIGHT,
	CURRENT_BG: oriTopSlide.CONF.BUTTON_CURRENT_BG_SRC,
	NORMAL_BG: oriTopSlide.CONF.BUTTON_NORMAL_BG_SRC,
	
	init: function() {
		var self = this;
		
		this._initElements();
		
		$(this.model).change(function() {
			self.update();
		});
		
		var elementHTML =
			[this._getElementAt(-2),
			 this._getElementAt(-1),
			 this._getElementAt( 0)].join('');
		$(this.container).html(elementHTML);
		
		this.update();
	},
	
	_initElements: function() {
		var self = this;
		
		$(this.container).mouseout(function() {
			self.model.setShouldRotate(true);
		});
	},
	
	update: function() {
		if(this.model.currentIndex == this._currentIndex) {
			return;
		}
		var self = this;
		
		// indexの変化は1ずつしか起こらない想定。
		var diff = this.model.currentIndex - this._currentIndex;
		// ループ時のための補正
		if(diff < -1) {
			diff = 1;
		}
		else if(diff > 1) {
			diff = -1;
		}
		var moveForward = (diff == 1);
		
		this._currentIndex = this.model.currentIndex;
		var newElement = this._getElementAt(this._currentIndex + diff);
		var newHTML = (moveForward) ? 
			$(this.container).html() + newElement :
			newElement + $(this.container).html();
			
		$(this.container).html(newHTML);
		
		
		this._removeCurrent($(this.container).children()[(moveForward) ? 1 : 2]);
		this._setCurrent($(this.container).children()[(moveForward) ? 2 : 1]);
		
		// アニメーション終了時にコンテナ内を再構成するためのcallback
		var callback = function() {
			$(self.container).css({
				marginTop: '0px'
			});
			
			var elementHTML = 
				[self._getElementAt(self._currentIndex-1),
				 self._getElementAt(self._currentIndex),
				 self._getElementAt(self._currentIndex+1)].join('');
			$(self.container).html(elementHTML);
			
			self._setCurrent($(self.container).children()[1]);
			
			$(self.container).children().each(function(index) {
				//trace($(this).children()[0].onclick);
				//$(this).onclick = function(e){ e.preventDefault(); trace("foo");};
				//trace("hm???" + $(this).html());
				//trace("oncli?" + $(this)[0].attr('onclick'))
				//trace("oncli?" + $(this)[1].onclick);
				if(index != 1) {
					$(this).children()[0].onclick = null;
				}
				
				$(this).click(function(e) {
					if(index != 1) {
						// currentのボタン以外はリンクを動作させない
						e.preventDefault();
						self.model.updateIndex(self._currentIndex + index - 1);
					}
				});
			});
		};
		
		var dest;
		if(moveForward) {
			dest = -this.BUTTON_HEIGHT;
		}
		else {
			$(this.container).css({
				marginTop: '-' + this.BUTTON_HEIGHT + 'px'
			});
			dest = 0;
		};
		
		$(this.container).animate({
			marginTop:dest + 'px'
		}, 500, 'swing', callback);
	},
	
	_setCurrent: function(element) {		
		$(element).css({
			backgroundImage: 'url(' + this.CURRENT_BG + ')'
		});
	},
	
	_removeCurrent: function(element) {
		$(element).css({
			backgroundImage: 'url(' + this.NORMAL_BG + ')'
		})
	},
	
	_getElementAt: function(index) {
		index = this._modifyIndex(index);
		return this.elementHTMLList[index];
	},
	
	/**
	 * -6 とか 20 などの突飛なindexを補正して返す。
	 */
	_modifyIndex: function(index) {
		if(index < 0) {
			index = this.numElements + (index % this.numElements);
		}
		return (index % this.numElements);
	}
};


/*
 * ModelのcurrentIndexを一定間隔で増やしていくもの。
 * 一定時間で自動ローテーションするためのモーター。
 */
 
oriTopSlide.Rotator = function(model, interval) {
	this.model = model;
	this.interval = (interval) ? interval : 2000;
	this.init();
};

oriTopSlide.Rotator.prototype = {
	init: function() {
		var self = this;
		$(this.model).change( function() {
			(self.model.shouldRotate) ?
				self.start() :
				self.stop();
		});
	},
	
	start: function() {
		if(this.intervalId) {
			clearInterval(this.intervalId);
		}
		var self = this;
		this.intervalId = setInterval(function() {
			self.increment();
		}, this.interval);
	},
	
	stop: function() {
		clearInterval(this.intervalId);
	},
	
	reset: function() {
		this.stop();
		this.start();
	},
	
	increment: function() {
		this.model.updateIndex(this.model.currentIndex + 1);
	}
};


// util
function trace(value) {
	if(window.console && console.log) {
		console.log(value);
	}
}


