/* ------------------
 NAMESPACE
------------------ */

Blockster = function(params, indexOfSlideToTurnOn) {

	
	
	
	/* ------------------
	 PREP & CONFIG DEFAULTS
	------------------ */

	var thiss = this;
	this.conf = {}; //config
	this.conf.blocks = {rows: 6, cols: 8} // 初期設定のブロック default:10*10
	this.conf.animType = 'fade'; // ブロックのアニメーションタイプ default:fade
	this.conf.blockAnimSpeed = 100; // ブロックのアニメーションが始まる間隔
	this.conf.blockFadeTime = 2000; //　ブロックのフェードインタイム
	this.conf.pause = 5000;
	this.params = params;
	this.clickActionQueueInt = true;

	//現スライド番号
	this.slideNum = 0;
	
	/* ------------------
	 params.holderが無かったら、returnfalse, その他のparamsが無かったら、confの値をつかう。
	------------------ */
	
	// params.holder:スライド対象 ex:"#slide"
	
	if (!this.params.holder || $(this.params.holder).length != 1) {
		//console.log("Blockster error: could not find holder element '"+this.params.holder+"'");
		return false;
	}

	this.params.holder = $(this.params.holder);
	if (!this.params.pause || !parseInt(this.params.pause)) this.params.pause = this.conf.pause;
	if (!this.params.blockAnimSpeed || !parseInt(this.params.blockAnimSpeed)) this.params.blockAnimSpeed = this.conf.blockAnimSpeed;
	if (!this.params.blockFadeTime || !parseInt(this.params.blockFadeTime)) this.params.blockFadeTime = this.conf.blockFadeTime;
	if (!this.params.rows || !parseInt(this.params.rows)) this.params.rows = this.conf.blocks.rows;
	if (!this.params.cols || !parseInt(this.params.cols)) this.params.cols = this.conf.blocks.cols;


	/* ------------------ */ 
	/* !PREP */
	/*------------------ */

	this.params.holder.children("div").addClass("banner");


	// holderの高さと幅
	this.params.holder.dimensions = {width: this.params.holder.width(), height: this.params.holder.height()};
	// ブロック一つの高さと幅
	this.params.dimensions = {
		width: Math.ceil(this.params.holder.dimensions.width / this.params.cols),
		height: Math.ceil(this.params.holder.dimensions.height / this.params.rows)
	};



	// indexOfSlideToTurnOn(引数) が falseの時, holderの中のdivの最初のもの以外hide
	if (!indexOfSlideToTurnOn) this.params.holder.children('div').hide(); //to start with, hide all slides but first

	/* ------------------*/
	/* ! controller interface */
	/*------------------ */
	
	if(this.params.holder.children(".banner") > 1){
		for(var i = 0; i < $(this.params.holder).find("img").length; i++){
			$("#controll").append("<li><div id='controll"+i+"'></div></li>");
		}
	}
	
	
	
	/*
$("#controll li div").click(function(e){
		var tarNum = $(e.target).attr("id").replace("controll","");
		thiss.jump(tarNum)
	})
*/
	
	
	$("#controll li div:eq(0)").addClass("current");



	/* ------------------------ */
	/* !if params OK, do effect */
	/* ------------------------ */

	thiss.func(0);
	// runOnceOnlyがfalseの時
	if (!this.params.runOnceOnly && this.params.holder.children(".banner").length > 1) {

		//console.log(indexOfSlideToTurnOn);
		var delay = this.params.pause + ((this.params.rows * this.params.cols) * this.params.blockAnimSpeed );
		//console.log(delay)
		if (!indexOfSlideToTurnOn)
		//console.log(indexOfSlideToTurnOn);
			//thiss.func();
			thiss.autoInt = setInterval(function() { thiss.func(); }, delay);
	}
	

	


};


/* ------------------
 MAIN FUNC (トランジションの度、実行される)
------------------ */

Blockster.prototype.func = function(indexOfSlideToTurnOn) {
	

	
	/* ------------------ */
	/* ! prep */
	/*------------------ */
	var thiss = this;

	/* ------------------
	 ascertain current and next slides (find :visible <div>, then next is either is prev sibling or, if none, parent's last child)
	------------------ */

	

	// 現在のスライド
	var currentSlide = this.params.holder.children('div:visible');
	// 次のスライド
	
	var nextSlide;
	
	if(indexOfSlideToTurnOn == undefined){
		//console.log(indexOfSlideToTurnOn);

		if(currentSlide.nextAll().length != 0){
			nextSlide = currentSlide.next();
			this.slideNum++;
		}else{
			nextSlide = this.params.holder.children('div').first();
			this.slideNum = 0;
						
		}
	}else{
		this.slideNum = indexOfSlideToTurnOn;
		nextSlide = this.params.holder.children('div').eq(indexOfSlideToTurnOn);
	}
	
	$("#controll li div.current").removeClass("current");
	$("#controll li div:eq("+this.slideNum+")").addClass("current");
	
	/*
var nextSlide = !indexOfSlideToTurnOn ?
						currentSlide.nextAll().length != 0 ? currentSlide.next() : this.params.holder.children('div').first() :
					this.params.holder.children('div').eq(indexOfSlideToTurnOn);
*/

	/* ------------------
	 Iterate over number of required blocks to be built. For each...
	------------------ */
	
	for(var u=0; u<(this.params.rows * this.params.cols); u++) {


		/* ------------------
		 ...DOM-script the block and style/position it (position depends on number of rows/cols and block dimensions, worked out at top)
		 Remember to start each block as hidden, so we can bring them in randomly when all are ready.
		------------------ */
		
		//blockを作って予め消しておく
		var block = document.createElement('div');
		var left, top;
		$(block)
			.css({
				width: this.params.dimensions.width,
				height: this.params.dimensions.height,
				left: (left = (u % this.params.cols) * this.params.dimensions.width),
				top: (top = Math.floor(u / this.params.cols) * this.params.dimensions.height),
				zIndex: 10000,
				overflow: 'hidden',
				position: 'absolute'
			})
			.hide()
			.addClass('block');

		/* ------------------
		 ...clone next slide and append it to the block, positioning it so only the right part of it shows (hence overflow:hidden on blocks)
		 Remember to unhide it!
		------------------ */
		
		//block一つ一つの中にpositionをずらした次のスライドをappendしていく。
		var nextSlide_clone = nextSlide.get(0).cloneNode(true);
		
		$(nextSlide_clone).css("display","block");
			
		$(nextSlide_clone).css({
				height: this.params.holder.height(),
				width: this.params.holder.width(),
				position: 'relative',
				left: -1*left,
				top: -1*top
			});
		
		$(block).append(nextSlide_clone);

//		alert(nextSlide);
		/* ------------------
		 ...append it to holder
		------------------ */

		this.params.holder.append($(block));
		
		block = null;
		delete block;
		nextSlide_clone = null;
		delete nextSlide_clone;
		
	}
	
	//for文おわり。

	/* ------------------
	 ANIMATION - with all blocks built, set an interval to turn them all on, one by one.
	 When all blocks in position, and all have finished anim (if fade rather than simple)
		- kill int
		- shuffle slides so the one our blocks contain parts of is genuinely topmost
		- remove blocks
	------------------ */

	var bNum = 0;
	var bTopNum = 0;
	var blocks = thiss.params.holder.children('.block');
	//blockのアニメーション
	
	var animInt = setInterval(function() {
		//ブロックのうち消えている物が１つ以上あるとき
		if(thiss.params.holder.children('.block:hidden').length > 0) {

			//どういう順番で表示するかはここで決めている。

			var bNumArr = new Array();
			bNum = bTopNum;
			do{
				bNumArr[bNumArr.length] = bNum;
				bNum += thiss.params.cols - 1;
			}while( bNum < blocks.length && bNum >= (Math.floor( (bNum - thiss.params.cols + 1) / thiss.params.cols) +1 ) * thiss.params.cols);

			for(var i = 0, len = bNumArr.length ; i < len; i++){
				$(blocks[bNumArr[i]]).fadeIn(thiss.params.blockFadeTime);
			}

			if(bTopNum < thiss.params.cols-1){
				bTopNum++;
			}else{
				bTopNum = bTopNum + thiss.params.cols;
			}
			
			bNumArr = null;
			delete bNumArr;

		}
		//ブロック全て表示後
		else if ($('#slide .block:animated').length == 0) {
			
			clearInterval(animInt);

			animInt = null;

			delete animInt;


			nextSlide.siblings().css("display","none");
			nextSlide.css("display","block");
			//alert();
			$('#slide .block').remove();
			bNum = 0;
			
			blocks = null;
			delete blocks;
			
		}
	}, thiss.params.blockAnimSpeed);

}


/* ------------------
 JUMP - allow user to control Blockster by interrupting auto-int and forcing a particular slide to load. Kills auto-int. If transition currently
 in progress, wait until after finished before acting. If another click logged while waiting, forget previous click (cancel its wait queue)
------------------ */

Blockster.prototype.jump = function(slideIndex) {
	//console.log(this.clickActionQueueInt);
	if (this.clickActionQueueInt) {
		clearInterval(this.clickActionQueueInt); 
		this.clickActionQueueInt = false; 
	}
	var thiss = this;
	this.clickActionQueueInt = setInterval(function() {
		if (thiss.params.holder.children('.block').length == 0) {

			clearInterval(this.autoInt);
			thiss.func(slideIndex);
			clearInterval(thiss.clickActionQueueInt);
			thiss.clickActionQueueInt = false;
		}
	}, 10);
}
