/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       Slide canvas.
 *
 *    @version rev012.2008-07-12
 *    @requires smoothScroll.js
 *    @requires slideCanvas.css
 */
/* -------------------------------------------------------------------------- */

BAImportJS('smoothScroll.js');


var BA_SLIDECANVAS_INSTANCES = [];



/* -------------------- Settings for BASlideCanvas -------------------- */

var BASLIDECANVAS_DURATION      = 375;
var BASLIDECANVAS_INTERVAL      = 1;
var BASLIDECANVAS_VISIBLE_UNITS = 2;
var BASLIDECANVAS_EASING_FUNC   = function(t, b, c, d) {
	// cubic easing in/out
	if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
	return c / 2 *((t -= 2) * t * t + 2) + b;
}



/* -------------------- Settings for BASlideCanvasAutoSetup -------------------- */

var BASLIDECANVAS_AS_ENABLED         = true;
var BASLIDECANVAS_AS_ROTATE_INTERVAL = 0;
var BASLIDECANVAS_AS_TARGET_CNAMES   = ['slide-canvas'];



/* -------------------- Constructor : BASlideCanvas -------------------- */

function BASlideCanvas(node, interval) {
	if (!node || node.instanceOf != 'BAElement') {
		throw 'BASlideCanvas: first argument must be a BAElement node.';
	}

	this.node           = node;
	this.rotateInterval = (interval > 0) ? interval : 0;
	this.rotateTimer    = null;
	this.scrollField    = null;
	this.slideNodes     = [];
	this.selectButton   = [];
	this.stepButton     = { prev : null , next : null };
	this.currentNum     = 0;
	this.fontSizeObserver = null;

	if (BA.env.isDOMReady) {
		this.init();
		this.startRotate();
	}
}

BASlideCanvas.prototype.init = function() {
	var viewportNode   = this.node.getElementsByClassNameBA('slide-viewport'  , 'div')[0];
	var controllerNode = this.node.getElementsByClassNameBA('slide-controller', 'ul' )[0];
	if (!viewportNode || !controllerNode) {
		throw 'BASlideCanvas.init: essential nodes are not found.';
	} else {
		// init scroll field.
		this.scrollField = new BASmoothScrollField(
			/* node     */ viewportNode,
			/* offsetX  */ (BA.ua.isSafari) ? -4 : 0,
			/* offsetY  */ 0,
			/* duration */ BASLIDECANVAS_DURATION,
			/* interval */ BASLIDECANVAS_INTERVAL,
			/* func     */ BASLIDECANVAS_EASING_FUNC
		);
		this.initScrollReviser(viewportNode); // for Gecko, temporary

		// prepare slide nodes.
		this.slideNodes = viewportNode.getElementsByClassNameBA('slide-unit', 'dl');

		if (this.slideNodes.length == BASLIDECANVAS_VISIBLE_UNITS) {
			// indicate discarded className
			this.node.appendClassNameBA('slide-canvas-discarded');
		} else if (this.slideNodes.length > BASLIDECANVAS_VISIBLE_UNITS) {
			// indicate enabled className
			this.node.appendClassNameBA('slide-canvas-enabled');
			this.createWastingInsForOpera();      // for opera, temporary

			if (viewportNode.scrollWidth == 0) {  // safety for opera, temporary
				this.node.removeClassNameBA('slide-canvas-enabled');
			} else {
				// find control button node.
				var anchors = controllerNode.getElementsByTagNameBA('a');

				// create step buttons
				this.stepButton.prev = new BASlideCanvas_StepBtn(anchors.shift(), -1);
				this.stepButton.next = new BASlideCanvas_StepBtn(anchors.pop()  , +1);
				for (var kind in this.stepButton) {
					this.stepButton[kind].addCallBack('onclick', this.selectBy, this);
				}
	
				// create select buttons
				anchors.forEach(function(node, i) {
					var btn = new BASlideCanvas_SelectButton(node, i);
					btn.addCallBack('onclick', this.select, this);
					this.selectButton.push(btn);
				}, this);
				
				// select first slide.
				this.select(0);
			}
		}

		if (typeof(BAFontSizeObserver) != "undefined") {
			this.fontSizeObserver = BASingleton(BAFontSizeObserver);
			this.fontSizeObserver.addCallBack("onChange", function(){
				this.select(this.currentNum);
				var maxHeight = 0;
				this.slideNodes.forEach(function(node){
					maxHeight = Math.max(maxHeight, node.offsetHeight);
				}, this);
				if (maxHeight) {
					BASLIDECANVAS_VISIBLE_UNITS = Math.floor(this.node.offsetHeight / maxHeight);
				}
			}, this);
			this.fontSizeObserver.startObserve();
		}
	}
}

/**
 * revise scrollLeft on manual scrolling (for Gecko only, temporary).
 * @private
 */
BASlideCanvas.prototype.initScrollReviser = function(viewportNode) {
	if (!BA.ua.isGecko) return;

	var lock = false;
	var posY = 0;
	this.scrollField.addCallBack('onStart'   , function(x, y) { lock = true            });
	this.scrollField.addCallBack('onComplete', function(x, y) { lock = false; posY = y });
	viewportNode.addEventListenerBA('scroll', function(e) { if (!lock) e.currentTarget.scrollTop = posY });
}

/**
 * workaround for Opera.
 * @private
 */
BASlideCanvas.prototype.createWastingInsForOpera = function() {
	if (!BA.ua.isOpera) return;

	var slide = this.slideNodes[0];
	if (slide) {
		var ins   = document.createElementBA('ins');
		ins.appendChildBA('.');
		ins.style.position   = 'relative';
		ins.style.left       = '-10px';
		ins.style.top        = '-10px';
		ins.style.display    = 'block';
		ins.style.width      = '1px';
		ins.style.height     = '1px';
		ins.style.fontSize   = '1px';
		ins.style.color      = 'transparent';
		ins.style.lineHeight = '0';
		slide.appendChildBA(ins);
	}
}

BASlideCanvas.prototype.select = function(num) {
	if (typeof num != 'number') {
		return;
	} else {
		this.startRotate();  // reset timer and continue rotation.

		var node = this.slideNodes[num];
		if (node) {
			// scroll slides.
			this.scrollField.stop();
			this.scrollField.scrollToNode(node);

			// select/unselect select buttons
			this.selectButton.forEach(function(btn, i) {
				if (num == i) {
					btn.select();
				} else {
					btn.unselect();
				}
			});

			// enable/disable step buttons
			this.stepButton.prev.enable();
			this.stepButton.next.enable();
			if (num == 0) {
				this.stepButton.prev.disable();
			} else if (num == this.slideNodes.length - BASLIDECANVAS_VISIBLE_UNITS) {
				this.stepButton.next.disable();
			}

			this.currentNum = num;
		}
	}
}

BASlideCanvas.prototype.selectBy = function(step) {
	if (typeof step != 'number' || step == 0) {
		return;
	} else {
		var len = this.currentNum.length;
		var num = this.currentNum + step;
		if (!this.slideNodes[num]) {
			num = (step > 0) ? 0 : this.slideNodes.length + step;
		}
		this.select(num);
	}
}

BASlideCanvas.prototype.startRotate = function() {
	this.stopRotate();
	BA.disableSiteCatalyst();
	if (this.rotateInterval > 0) {
		this.rotateTimer = new BASetInterval(function() { this.selectBy(1) }, this.rotateInterval, this);
	}
}

BASlideCanvas.prototype.stopRotate = function() {
	if (this.rotateTimer) {
		this.rotateTimer.clearTimer();
		this.rotateTimer = null;
	}
	BA.resumeSiteCatalyst();
}



/* -------------------- Constructor : BASlideCanvas_StepBtn inherits BAObservable -------------------- */

function BASlideCanvas_StepBtn(node, step) {
	this.node     = node;
	this.step     = step;
	this.disabled = false;

	if (BA.env.isDOMReady) {
		this.init();
	}
}

BASlideCanvas_StepBtn.prototype = new BAObservable;

BASlideCanvas_StepBtn.prototype.init = function() {
	this.rollover = new BARollover(this.node, {
		'normal'     : '',
		'hover'      : '_o',
		'disable'    : '_d'
	});
	this.node.addEventListenerBA('click', this.onclick, this);
	this.node.addEventListenerBA('mouseenter', function(){
		if (!this.disabled) {
			this.rollover.setStatus('hover');
		}
	}, this);
	this.node.addEventListenerBA('mouseleave', function(){
		if (!this.disabled) {
			this.rollover.setStatus('normal');
		}
	}, this);
}

BASlideCanvas_StepBtn.prototype.onclick = function(e) {
	e.preventDefault();
	if (!this.disabled) {
		this.doCallBack('onclick', this.step);
	}
}

BASlideCanvas_StepBtn.prototype.enable = function() {
	this.disabled = false;
	if (this.rollover.getStatus() == 'hover') {
		this.rollover.setStatus('hover');
	} else {
		this.rollover.setStatus('normal');
	}
	this.node.removeClassNameBA('pseudo-disabled');
}

BASlideCanvas_StepBtn.prototype.disable = function() {
	this.disabled = true;
	this.rollover.setStatus('disable');
	this.node.appendClassNameBA('pseudo-disabled');
}



/* -------------------- Constructor : BASlideCanvas_SelectButton inherits BAObservable -------------------- */

function BASlideCanvas_SelectButton(node, index) {
	this.node     = node;
	this.index    = index;
	this.selected = false;

	if (BA.env.isDOMReady) {
		this.init();
		
	}
}

BASlideCanvas_SelectButton.prototype = new BAObservable;

BASlideCanvas_SelectButton.prototype.init = function() {
	this.node.addEventListenerBA('click', this.onclick, this);
}

BASlideCanvas_SelectButton.prototype.onclick = function(e) {
	e.preventDefault();
	this.doCallBack('onclick', this.index);
}

BASlideCanvas_SelectButton.prototype.select = function() {
	this.selected = true;
	this.node.appendClassNameBA('pseudo-selected');
}

BASlideCanvas_SelectButton.prototype.unselect = function() {
	this.selected = false;
	this.node.removeClassNameBA('pseudo-selected');
}







/* -------------------- Function : BASlideCanvasAutoSetup -------------------- */

function BASlideCanvasAutoSetup() {
	BASLIDECANVAS_AS_TARGET_CNAMES.forEach(function(className) {
		document.getElementsByClassNameBA(className, 'div').forEach(function(node) {
			BA_SLIDECANVAS_INSTANCES.push(
				new BASlideCanvas(node, BASLIDECANVAS_AS_ROTATE_INTERVAL)
			);
		});
	});
}






/* -------------------- Main : register start-up -------------------- */

if (typeof BA == 'object' && BA.ua.isDOMReady && BASLIDECANVAS_AS_ENABLED) {
	BAAddOnload(BASlideCanvasAutoSetup);
}


