/* -------------------------------------------------------------------------- */
/**
 *    @fileoverview
 *       Pseudo Dialog.
 *
 *    @version rev012.2008-07-25
 *    @requires common.js
 *    @requires balloon.js
 *    @requires keyEquiv.js
 *    @requires effect.js
 *    @requires processingInfo.js
 *    @requires pseudoDialog.css
 *    @requires pseudoDialogContent.js (in dialog content pages)
 */
/* -------------------------------------------------------------------------- */


var BA_PSEUDODIALOG;
var BA_PSEUDODIALOG_PREVIOUS_FOCUSED_ANCHOR;



/* --------------- Settings for BAPseudoDialog --------------- */

var BA_PSEUDODIALOG_OFFSET          = { X : 0   , Y : 0    };
var BA_PSEUDODIALOG_USE_CENTERING   = { X : true, Y : true };
var BA_PSEUDODIALOG_CONTENT_MAXSIZE = { W : 944 , H : 0    };
var BA_PSEUDODIALOG_LOADING_TIMEOUT = 30000;



/* --------------- Settings for BAPseudoDialogAutoSetup --------------- */

var BA_PSEUDODIALOG_AS_TARGET_NAME = 'pseudoDialog';



/* --------------- Constructor : BAPseudoDialog inherits BABalloon --------------- */

function BAPseudoDialog() {
	this.id                   = 'BAPseudoDialog';
	this.offsetX              = BA_PSEUDODIALOG_OFFSET.X;
	this.offsetY              = BA_PSEUDODIALOG_OFFSET.Y;
	this.delay                = 0;
	this.sustain              = 0;
	this.posRevise            = { X : false, Y : false };
	this.useCentering         = BA_PSEUDODIALOG_USE_CENTERING;
	this.contentFrame         = null;
	this.contentFrameName     = 'BADialogContent';
	this.contentFrameMaxSize  = BA_PSEUDODIALOG_CONTENT_MAXSIZE;
	this.contentURL           = 'about:blank';
	this.pseudoDialogContent  = null;
	this.allowDialogOpen      = false;
	this.activatedCName       = 'BAPseudoDialogIsActive';
	this.timeoutTimer         = null;
	this.effect               = null;
	this.BAProcessingInfo     = null;
	this.shields = [];

	if (BA.env.isDOMReady) {
		this.init();
	}
}

BAPseudoDialog.prototype           = new BABalloon;
BAPseudoDialog.prototype.initSuper = BAPseudoDialog.prototype.init;

BAPseudoDialog.prototype.init = function() {
	this.initSuper();
//	this.setPositionFixed();  // this makes scroll bovine in WinIE7
	this.createContentFrame();
	this.adjustSize(1, 1);
	this.moveTo(-10000, 0);
	window.addEventListenerBA('resize', function() { if (this.active) this.moveDialogToCenter() }, this);

	// set key equivalents
	if (typeof BA_KEYEQUIV == 'object') {
		BA_KEYEQUIV.addKeyEquiv('!', this.close, this);
	}

	// init animation effect.
	this.effect = new BAEffect.Resize(this.node, 750);
	this.effect.addCallBack('onComplete', function() { BASingleton(BAClickShield).adjustSize() });

	// register shields.
	this.shields.push(BASingleton(BAClickShield   ));
	this.shields.push(BASingleton(BATabFocusShield));
//	this.shields.push(BASingleton(BAScrollShield  ));

	// event handling on the shields.
	BASingleton(BAClickShield   ).addCallBack('onPrevented', this.close          , this);
	BASingleton(BATabFocusShield).addCallBack('onPrevented', this.setDefaultFocus, this);
}

BAPseudoDialog.prototype.createContentFrame = function() {
	if (!this.contentFrame) {
		var iframe = new BATag('iframe');
		iframe.setAttributeBA('name', this.contentFrameName);
		iframe.setAttributeBA('src' , 'about:blank');
		iframe.setAttributeBA('border'     , '0' );
		iframe.setAttributeBA('frameborder', '0' );
		iframe.setAttributeBA('scrolling'  , 'no');
		iframe.appendChildBA('');
		this.setContent(iframe);
		this.contentFrame = this.node.getElementsByTagNameBA('iframe')[0];
	}
}

BAPseudoDialog.prototype.open = function(url) {
	if (!url || typeof url != 'string') {
		throw 'BAPseudoDialog.open: first argument must be an URL string.';
	} else if (!this.active) {
		this.allowDialogOpen = true;
		this.shields.forEach(function(shield) { shield.enable() });
		BASingleton(BAClickShield).addCallBack(
			  'onEnable'
			, function() { this.loadContent(url, BA_PSEUDODIALOG_LOADING_TIMEOUT) }
			, this
			, 'disposable'
		);
		if (typeof BA_PROCESSING_INFO == 'object') {
			BA_PROCESSING_INFO.show();
		}
	}
}

BAPseudoDialog.prototype.loadContent = function(url, timeout) {
	this.clearTimeoutTimer();
	if (timeout > 0) {
		this.timeoutTimer = new BASetTimeout(this.close, timeout, this);
	}
	window.frames[this.contentFrameName].location.replace(url);
	this.contentURL = url; // temporary
}

BAPseudoDialog.prototype.showDialog = function(content) {
	if (!content) {
		throw 'BAPseudoDialog.showDialog: first argument must be a BAPseudoDialogContent instance.';
	} else {
		// preparations.
		this.clearTimeoutTimer();
		BAAppendStateClassName(this.activatedCName);
		this.pseudoDialogContent = content;

		// add callbacks to dialog content. (temporary)
		this.pseudoDialogContent.addCallBack('onCancelBtnClicked', this.close, this);

		// show dialog.
		this.adjustSize();
		this.moveDialogToCenter();

		var geom = this.getGeometry();
		this.resizeTo(geom.width, 1);
		this.show();
		this.effect.resizeTo(geom.width, geom.height, this.setDefaultFocus, this);

		if (typeof BA_PROCESSING_INFO == 'object') {
			new BASetTimeout(function() { BA_PROCESSING_INFO.hide(); }, 250);
		}
	}
}

BAPseudoDialog.prototype.close = function() {
	if (!this.active) return;
	
	this.clearTimeoutTimer();
	var geom = this.getGeometry();
	this.effect.resizeTo(
		  geom.width
		, 1
		, function() {
			BARemoveStateClassName(this.activatedCName);
			this.hide();
			this.adjustSize(1, 1);
			this.moveTo(-10000, 0);
			this.shields.forEach(function(shield) { shield.disable() });
			this.loadContent('about:blank');
		  }
		, this
	);
	if (typeof BA_PROCESSING_INFO == 'object') {
		BA_PROCESSING_INFO.hide();
	}
}

BAPseudoDialog.prototype.adjustSize = function(width, height) {
	if (/* BA.ua.isOpera || */ BA.ua.isMacIE) return;
	if (BA.ua.isSafari && parseFloat(BA.ua.revision) <= 100) return;
	if (isNaN(width) || isNaN(height)) {
		var contentGeom = this.pseudoDialogContent.getGeometry();
		width  = (this.contentFrameMaxSize.W > 0) ? Math.min(contentGeom.pageW, this.contentFrameMaxSize.W) : contentGeom.pageW;
		height = (this.contentFrameMaxSize.H > 0) ? Math.min(contentGeom.pageH, this.contentFrameMaxSize.H) : contentGeom.pageH;
	}
	this.contentFrame.width  = width  + 'px';
	this.contentFrame.height = height + 'px';
	this.resizeTo(width, height);
	BASingleton(BAClickShield).adjustSize();
}

BAPseudoDialog.prototype.moveDialogToCenter = function() {
	this.moveToCenter(this.useCentering);
}

BAPseudoDialog.prototype.setDefaultFocus = function() {
	if (this.active && !BA.ua.isOpera) {
		this.pseudoDialogContent.setDefaultFocus();
	}
}

BAPseudoDialog.prototype.clearTimeoutTimer = function() {
	if (this.timeoutTimer) {
		this.timeoutTimer.clearTimer();
	}
	this.timeoutTimer = null;
}





/* --------------- Constructor : BAClickShield inherits BABalloon --------------- */

function BAClickShield() {
	this.id        = 'BApseudoDialogShield';
	this.offsetX   = 0;
	this.offsetY   = 0;
	this.delay     = 0;
	this.sustain   = 0;
	this.posRevise = { X : false, Y : false };
	this.effect    = null;

	if (BA.env.isDOMReady) {
		this.init();
	}
}

BAClickShield.prototype           = new BABalloon;
BAClickShield.prototype.initSuper = BAClickShield.prototype.init;

BAClickShield.prototype.init = function() {
	this.initSuper();
	this.moveTo(0, 0);
	this.node.addEventListenerBA('click' , this.eventPreventer, this);
	window   .addEventListenerBA('resize', this.adjustSize    , this);

	this.effect = new BAEffect.Opacity(this.node, 500);
	this.effect.changeTo(0);
}

BAClickShield.prototype.eventPreventer = function(e) {
	if (this.active) {
		this.doCallBack('onPrevented');
	}
}

BAClickShield.prototype.adjustSize = function() {
	if (this.active) {
		var geom   = BAGetGeometry();
		var width  = (BA.ua.isIE55) ? geom.pageW : Math.max(geom.pageW, geom.windowW);
		var height = Math.max(geom.pageH, geom.windowH);

		if (BA.ua.isSafari) {
			var pdGeom = BASingleton(BAPseudoDialog).getGeometry();
			width  = Math.max(width , pdGeom.posX + pdGeom.width );
			height = Math.max(height, pdGeom.posY + pdGeom.height);
		}

		var reviseW = (geom.pageH > geom.windowH) ? geom.scrollBar : 0;
		var reviseH = 0;
		if (BA.ua.isWinIE) {
			reviseW = (BA.ua.revision < 7) ? geom.scrollBar + 4 : 0;
//			reviseH = (BA.ua.revision < 7) ? 4 : 0;
		} else if (BA.ua.isSafari && BA.ua.revision < 522) { /* Safari 2.0.x or ealier */
			reviseW = 0;
		}

		this.resizeTo(width - reviseW, height - reviseH);
	}
}

BAClickShield.prototype.enable = function() {
	this.show();
//	this.effect.fadeIn();
	this.effect.fadeTo(40, this.enableMain, this);
	new BASetTimeout(this.adjustSize, this.delay, this);

}

BAClickShield.prototype.disable = function() {
	this.effect.fadeOut(this.disableMain, this);
}

BAClickShield.prototype.enableMain = function() {
	this.doCallBack('onEnable');
}

BAClickShield.prototype.disableMain = function() {
	this.hide();
	this.resizeTo(1, 1);
	this.doCallBack('onDisable');
}



/* --------------- Constructor : BATabFocusShield inherits BAObservable --------------- */

function BATabFocusShield() {
	this.active = false;

	if (BA.env.isDOMReady) {
		this.init();
	}
}

BATabFocusShield.prototype = new BAObservable;

BATabFocusShield.prototype.init = function() {
	if (typeof BA_KEYEQUIV == 'object') {
		BA_KEYEQUIV.addKeyEquiv('|' , this.eventPreventer, this);
		BA_KEYEQUIV.addKeyEquiv('$|', this.eventPreventer, this);
	}
	var anchors = document.getElementsByTagNameBA('a');
	[anchors.shift(), anchors.pop()].forEach(function(anchor) {
		if (anchor) {
			anchor.addEventListenerBA('focus', this.eventPreventer, this);
		}
	}, this);
}

BATabFocusShield.prototype.eventPreventer = function(e) {
	if (this.active) {
		e.preventDefault();
		this.doCallBack('onPrevented');
	}
}

BATabFocusShield.prototype.enable = function() {
	var geom = BAGetGeometry();
	this.scrollPos = { X : geom.scrollX, Y : geom.scrollY };
	this.active    = true;
}

BATabFocusShield.prototype.disable = function() {
	this.active = false;
}






/* --------------- Constructor : BAScrollShield inherits BAObservable --------------- */

function BAScrollShield() {
	this.active = false;
	this.scrollPos = { X : 0, Y : 0 };

	if (BA.env.isDOMReady) {
		this.init();
	}
}

BAScrollShield.prototype = new BAObservable;

BAScrollShield.prototype.init = function() {
	window.addEventListenerBA('scroll', this.eventPreventer, this);
}

BAScrollShield.prototype.eventPreventer = function(e) {
	if (this.active) {
		e.preventDefault();
		window.scrollTo(this.scrollPos.X, this.scrollPos.Y);
		this.doCallBack('onPrevented');
	}
}

BAScrollShield.prototype.enable = function() {
	var geom = BAGetGeometry();
	this.scrollPos = { X : geom.scrollX, Y : geom.scrollY };
	this.active    = true;
}

BAScrollShield.prototype.disable = function() {
	this.active = false;
}







/* --------------- Function : BAPseudoDialogAutoSetup --------------- */

function BAPseudoDialogAutoSetup() {
	document.getElementsByTagNameBA('a').forEach(function(anchor) {
		if (anchor.target == BA_PSEUDODIALOG_AS_TARGET_NAME && anchor.href) {
			anchor.addEventListenerBA('click', function(e) {
				e.preventDefault();
				e.currentTarget.blur();
				BA_PSEUDODIALOG.open(e.currentTarget.href);
				BA_PSEUDODIALOG_PREVIOUS_FOCUSED_ANCHOR = e.currentTarget;
			});
		}
	});

	BA_PSEUDODIALOG.addCallBack('onHide', function() {
		try {
			BA_PSEUDODIALOG_PREVIOUS_FOCUSED_ANCHOR.focus();
		} catch(err) { }
	 });
}






/* -------------------- Main : register start-up -------------------- */

if (typeof BA == 'object' && typeof BABalloon == 'function' && typeof BAEffect == 'object' && BA.ua.isDOMReady) {
	BAAddOnload(function() {
		BA_PSEUDODIALOG = BASingleton(BAPseudoDialog);
		BAPseudoDialogAutoSetup();
	});
}


