/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       Image Swap / Rollover Control for Navigation
 *
 *    @version rev012.2008-12-16
 *    @requires common.js
 *    @requires rollover.js
 */
/* -------------------------------------------------------------------------- */



/* -------------------- Settings for BANavigationRollover -------------------- */

var BA_NAVIGATION_ROLLOVER_SETTINGS = {
	areaId     : 'global-nav',
	statusSet  : {
		'normal' : '',
		'hover'  : '_o'
	},
	delay      : 500
};



/* -------------------- Constructor : BANavigationRollover -------------------- */
/**
 * provides navigation rollover
 * @class navigation rollover controller
 * @constructor
 * @param {Object}  setting       navigation area, status-set, delay time. (required)
 */
function BANavigationRollover(setting) {
	this.items     = [];
	this.statusSet = {};
	this.delay     = 0;
	this.timer     = null;

	this.init(setting);
}

/** 
 * initialize, setup nodes.
 * @param {Object}  setting       navigation area, status-set, delay time. (required)
 * @private
 */
BANavigationRollover.prototype.init = function(setting){
	if (!setting || !setting.areaId) {
		return;
	}

	this.statusSet = setting.statusSet || {};
	this.delay     = setting.delay;

	var navArea = document.getElementByIdBA(setting.areaId);
	if (navArea) {
		var nav = navArea.getElementsByTagNameBA("ul")[0];
		if (nav) {
			var nodes = nav.childNodes;
			for (var i = 0, n = nodes.length; i < n; i++) {
				var node = nodes[i];
				if (node.nodeType == 1 && node.nodeName.toLowerCase() == "li") {
					this.addItem(node);
				}
			}
		}
	}
}

/** 
 * add navigation item.
 * @param {Element}  node       li element.
 * @private
 */
BANavigationRollover.prototype.addItem = function(node){
	BARegisterDOMMethodsTo(node);

	var item = new BANavigationRolloverItem(node, this.statusSet);

	var index = this.items.length;

	node.addEventListenerBA("mouseenter", function(){
		this.select(index);
	}, this);
	node.addEventListenerBA("mouseleave", function(){
		this.select();
	}, this);

	var links = node.getElementsByTagNameBA("a");
	links.forEach(function(link){
		link.addEventListenerBA("focus", function(){
			this.select(index);
		}, this);
		link.addEventListenerBA("blur", function(){
			this.select();
		}, this);

		if (link.getParentNodeBA() !== node) {
			var img = link.getElementsByTagNameBA("img")[0];
			if (img) {
				var swapper = new BAImageSwapper(img, this.statusSet);
				link.addEventListenerBA("mouseenter", function(){
					this.setStatus("hover");
				}, swapper);
				link.addEventListenerBA("mouseleave", function(){
					this.setStatus("default");
				}, swapper);
				link.addEventListenerBA("focus", function(){
					this.setStatus("hover");
				}, swapper);
				link.addEventListenerBA("blur", function(){
					this.setStatus("default");
				}, swapper);
			}
		}
	}, this);


	this.items.push(item);
}

/** 
 * clear timer.
 * @private
 */
BANavigationRollover.prototype.clearTimer = function(){
	if (this.timer) {
		this.timer.clearTimer();
		this.timer = null;
	}
}

/** 
 * select navigation item.
 * @param {Number}  index       index-number for select item.
 */
BANavigationRollover.prototype.select = function(index){
	this.clearTimer();
	if (!typeof(index) == "Number") {
		index = -1;
	}
	if (index > -1) {
		this.items.forEach(function(item, i){
			if (i == index) {
				item.setStatus("hover");
			} else {
				item.setStatus("default");
			}
		});
	} else {
		this.timer = new BASetTimeout(function(){
			this.items.forEach(function(item){
				item.setStatus("default");
			});
		}, this.delay, this);
	}
}



/* -------------------- Constructor : BANavigationRolloverItem inherits BARollover -------------------- */
/**
 * provides navigation rollover (this can apply to any elements, not only img element!)
 * @class navigation rollover
 * @constructor
 * @see BARollover
 * @param {Element} node            top-level element node of rollover behavior      (required)
 * @param {Object}  statusSet       associative array of status and it's suffix sign (required)
 * @param {String}  excludeCName    className for the image that is not expected to rollover
 */
function BANavigationRolloverItem(node, statusSet, excludeCName) {
	/** top-level element node of rollover behavior.
	    @type Element @const @private */
	this.node         = node;
	/** associative array of pairs of status and it's suffix sign.
	    @type Object @private */
	this.statusSet    = statusSet || {};
	/** current rollover status.
	    @type String @private */
	this.status       = 'default';
	/** prefix for 'pseudo className' added according to status.
	    @type String @const @private */
	this.cNamePrefix  = 'pseudo-';
	/** className for the image that is not expected to rollover
	    @type String @const @private */
	this.excludeCName = excludeCName || '';
	/** the array of BAImageSwapper instances.
	    @type Array @private */
	this.swappers     = [];
	
	if (BA.env.isDOMReady) {
		this.init();
	}
}
BANavigationRolloverItem.prototype = new BARollover;

/** 
 * initialize, setup nodes.
 * @private
 */
BANavigationRolloverItem.prototype.init = function() {
	if (!this.node || this.node.nodeType != 1) {
		throw 'BARollover: first argument must be an element node.';
	} else {
		var nodes = [BARegisterDOMMethodsTo(this.node)];
		node = this.node.getElementsByTagNameBA('img')[0];
		if (node && this.nodeValidate(node)) {
			this.swappers.push(new BAImageSwapper(node, this.statusSet));
		}
	}
}



/* -------------------- Main : register start-up -------------------- */

if (typeof BA == 'object' && BA.ua.isDOMReady) {
	BAAddOnload(function(){
		new BANavigationRollover(BA_NAVIGATION_ROLLOVER_SETTINGS);
	});
}
