/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       visual effects and animations library.
 *
 *    @version rev004.2007-09-16
 *    @requires common.js
 */
/* -------------------------------------------------------------------------- */

var BAEffect = {}



/* -------------------- Constructor : BAEffect.Resize inherits BAObservable -------------------- */
/**
 * animated resize effect object
 * @class animated resize effect
 * @constructor
 * @param {BAElement} node         radical node (a processing node in an appearance) (required)
 * @param {Number}    duration     animation duration (ms)
 * @param {Number}    interval     easing interval (ms)
 * @param {Function}  function     easing function
 */
/*!
 *  arguments of callback 'onStart(width, height)' :
 *      {Number} width     current offsetWidth  of the base node.
 *      {Number} height    current offsetHeight of the base node.
 * 
 *  arguments of callback 'onResize(width, height)' :
 *      {Number} width     current offsetWidth  of the base node.
 *      {Number} height    current offsetHeight of the base node.
 * 
 *  arguments of callback 'onComplete(width, height)' :
 *      {Number} width     current offsetWidth  of the base node.
 *      {Number} height    current offsetHeight of the base node.
 */
BAEffect.Resize = function(node, duration, interval, func) {
	if (!node || node.instanceOf != 'BAElement') {
		throw 'BAEffect.Resize: first argument must be a BAElement node.';
	}

	/** base node as processing target of this effect.
	    @type BAElement @private */
	this.node          = node;
	/** animation duration time (ms).
	    @type Number @private */
	this.duration      = (duration > 0) ? duration : 500;
	/** easing interval seconds (ms).
	    @type Number @private */
	this.interval      = (interval > 0) ? interval :  10;
	/** base node's style-width and style-height before resizing.
	    @type Object @private */
	this.fromSize      = { width : 0 , height: 0 };
	/** base node's style-width and style-height after resizing.
	    @type Object @private */
	this.toSize        = { width : 0 , height: 0 };
	/** animation interval timer.
	    @type BASetInterval @private */
	this.easingTimer   = null;
	/** animation elapsed timer.
	    @type BATimer @private */
	this.elapseTimer   = null;
	/** class name for effect base node.
	    @type String @private @const */
	this.baseNodeCName = 'BAEffectBase';

	if (BA.env.isDOMReady) {
		this.init();
		this.setEasingFunc(func);
	}
}

BAEffect.Resize.prototype = new BAObservable;

/**
 * initialize.
 * @private
 */
BAEffect.Resize.prototype.init = function() {
	if (!this.node.__BAEffectBase__) {
		this.node.__BAEffectBase__ = true;
		this.node.appendClassNameBA(this.baseNodeCName);
	}
}

/**
 * set easing function.
 * @param {Function} func    easing function.
 */
BAEffect.Resize.prototype.setEasingFunc = function(func) {
	if (typeof func == 'function' && typeof func(0, 0, 0, 0) == 'number') {
		this.easingFunc = func;
	}
}

/**
 * easing function - this can be replaced by using {@link #setEasingFunc}.
 * @param {Number} t    current time (seconds/milliseconds) (required)
 * @param {Number} b    beginning value (required)
 * @param {Number} c    change in value (required)
 * @param {Number} d    duration (seconds/milliseconds) (required)
 * @return solution value of the easing equation
 * @type Number
 * @private
 */
BAEffect.Resize.prototype.easingFunc = function(t, b, c, d) {
	// cubic easing in/out - acceleration until halfway, then deceleration
	if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
	return c / 2 *((t -= 2) * t * t + 2) + b;
}

/**
 * get base node's style-width and style-height.
 * @return associative array { width, height }
 * @type Object
 * @private
 */
BAEffect.Resize.prototype.getInnerSize = function() {
	var ret = {
		width  : this.node.offsetWidth,
		height : this.node.offsetHeight
	};
	return ret;
}

/**
 * resize width and height of the node with animation.
 * @param {Number} width     resizing width , if -1 given, no resize width  (required)
 * @param {Number} height    resizing height, if -1 given, no resize height (required)
 */
BAEffect.Resize.prototype.resizeTo = function(width, height) {
	this.clearTimer();

	if (width  === null) width  = -1;
	if (height === null) height = -1;

	var size = this.getInnerSize();
	this.fromSize.width  = size.width ;
	this.fromSize.height = size.height;
	this.toSize.width    = (width  >= 0) ? width  - this.node.offsetWidth  : 0;
	this.toSize.height   = (height >= 0) ? height - this.node.offsetHeight : 0;

	if (this.toSize.width != 0 || this.toSize.height != 0) {
		this.doCallBackByName('onStart');
		this.elapseTimer = new BATimer;
		this.easingTimer = new BASetInterval(this.resizeProcess, this.interval, this);
	} else {
		this.postProcess();
	}
}

/**
 * resizing main process.
 * @private
 */
BAEffect.Resize.prototype.resizeProcess = function() {
	var elapse = Math.min(this.elapseTimer.getTime(), this.duration);
	var width  = this.easingFunc(elapse, this.fromSize.width , this.toSize.width , this.duration);
	var height = this.easingFunc(elapse, this.fromSize.height, this.toSize.height, this.duration);
	if (elapse < this.duration) {
		if (this.toSize.width  != 0) this.node.style.width  = Math.max(Math.floor(width ), 0) + 'px';
		if (this.toSize.height != 0) this.node.style.height = Math.max(Math.floor(height), 0) + 'px';
		this.doCallBackByName('onResize');
	} else {
		if (this.toSize.width  != 0) this.node.style.width  = width  + 'px';
		if (this.toSize.height != 0) this.node.style.height = height + 'px';
		this.postProcess();
	}
}

/**
 * effect post process.
 * @private
 */
BAEffect.Resize.prototype.postProcess = function() {
	this.clearTimer();
	this.doCallBackByName('onComplete');
}

/**
 * clear animation timers.
 * @private
 */
BAEffect.Resize.prototype.clearTimer = function() {
	if (this.elapseTimer) {
		this.elapseTimer = null;
	}
	if (this.easingTimer) {
		this.easingTimer.clearTimer();
		this.easingTimer = null;
	}
}

/**
 * process callback.
 * @param {String} name    callback name (preferred to start with 'on') (required)
 * @private
 */
BAEffect.Resize.prototype.doCallBackByName = function(name) {
	this.doCallBack(name, this.node.offsetWidth, this.node.offsetHeight);
}



function resizeFlash(mode) {
	if (!window._effect && flash.node) {
		indexFlashResizeEffect();
	}
	if (window._effect && flash.node) {
		window._ResizeFlashAlreadyApplied = true;

		var geom   = BAGetGeometry();

		var minWidth  = 780;
		var minHeight = 456;

		var width  = geom.windowW;
		var height = geom.windowH - window._footer.offsetHeight - 1;

		if (BA.ua.isWinIE && BA.ua.revision < 7) {
			width  -= 21;
			height -= 3;
		}

		if (geom.zoom <= 1) {
			width     = parseInt(width     / geom.zoom);
			minWidth  = parseInt(minWidth  / geom.zoom);
			height    = parseInt(height    / geom.zoom);
			minHeight = parseInt(minHeight / geom.zoom);
		}

		width  = Math.max(minWidth,  width);
		height = Math.max(minHeight, height);

		if (!window._effect.initialized) {
			window._footer.style.visibility = "hidden";
			if (window._reviseTimer) {
				window._reviseTimer.clearTimer();
				window._reviseTimer = null;
			}

			flash.node.style.minHeight = minHeight + "px";
			flash.disableResize = true;

			var _func = arguments.callee;
			window._effect.setCallBack("onComplete", function(){
				flash.node.style.visibility = "hidden";
				new BASetTimeout(function(){
						flash.node.style.visibility = "visible";
				}, 1);
				if (BA.ua.isWinIE) {
					window.addEventListenerBA("beforeprint", function(){
						window._contents.style.height = "auto";
					});
				}
				if (!(BA.ua.isWinIE && BA.ua.revision >= 7)) {
					window.addEventListenerBA("resize", _func);
				}
				if (/Firefox/.test(navigator.userAgent)) {
					window.addEventListenerBA("resize",function(){
						window.scrollBy(1, 1);
						window.scrollBy(-1, -1);
					});
				}
				new BASetInterval(_func, 300)
			});
			window._contents.style.height = height + "px";
			window._effect.resizeTo(width, height);
			window._effect.initialized = true;
			window._footer.style.visibility = "visible";
			document.getElementsByTagNameBA("body")[0].appendClassNameBA("movie");
		} else {
			var flashStyle = flash.node.style;
			flashStyle.width  = (BA.ua.isMac && /Firefox/.test(navigator.userAgent)) ? "100%" : width + "px";
			flashStyle.height = height + "px";
			window._contents.style.height = flashStyle.height;
		}
	} else {
		new BASetTimeout(arguments.callee, 100);
	}
}

if (typeof BA == 'object' && BA.ua.isDOMReady) {
	function indexFlashResizeEffect() {
		if (window._timer) {
			window._timer.clearTimer();
			window._timer = null;
		}
		if (flash.node) {
			if (window._effect) {
				return;
			}
			window._contents = document.getElementByIdBA("contents-area");
			window._footer = document.getElementByIdBA("footer");
			window._effect = new BAEffect.Resize(flash.node);
		} else {
			new BASetTimeout(arguments.callee, 100);
		}
	}
}

