/**
 * @author Sergey Chikuyonok (gonarch@design.ru)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru) 
 */

/**
 * Menu expanding mechanism
 * @constructor
 * @param {String, Element} elem
 */
vtb24.menu=function(elem){
	this.dontCollapse=false;
	this.setContainer(elem);
};

/**
 * Set menu container
 * @param {String, Element} elem
 */
vtb24.menu.prototype.setContainer=function(elem){
	this._container=als.getElement(elem);
	var menues=this._container.getElementsByTagName('ul');
	for(var i=0; i<menues.length; i++)
		this._cleanUp(menues[i]);
	this.attachEvents(this._container);
};

/**
 * Returns menu container element
 * @return {Element}
 */
vtb24.menu.prototype.getContainer=function(){
	return this._container;
};

/**
 * Set currently expanded menu
 * @param {Element} elem Menu
 */
vtb24.menu.prototype.setExpandedMenu=function(elem){
	if(elem)
		Common.Class.add(elem, 'expanded');
	this._expanded=elem;
};

/**
 * Get currently expanded menu
 * @return {Element}
 */
vtb24.menu.prototype.getExpandedMenu=function(){
	return this._expanded;
};

/**
 * Attach menu events for container
 * @param {Element} elem Container
 */

vtb24.menu.prototype.attachEvents=function(elem){
	var me=this;
	var f=function(evt){return me.dispatchEvent(evt);}
	
	Common.Event.add(document, 'click', function(evt){
		me.lastClickedItem = false;
		return me.collapseLastExpanded(Common.Event.normalize(evt));
	});
	
	Common.Event.add(window, 'resize', function (evt) {
		window.setTimeout( function () { me.onResize( evt ); }, 1);
		return me.onResize(evt);
	});

//	23.10.2009 @serge - commented the following part because of errors in menu close event handling and because of weirdness of the event itself    
//	Common.Event.add(window, 'MozAfterPaint', function (evt) {
//		window.setTimeout( function () { me.onResize( evt ); }, 1);
//		return me.onResize(evt);
//	});
	
	var root_menu=elem.getElementsByTagName('ul')[0], items;
	if(!root_menu)
		return;
	var ch=root_menu.childNodes, ch2;
	var il=ch.length;
	for(var i=0; i<il; i++){
		if(ch[i].nodeType == 1 && ch[i].nodeName == 'LI'){
			items=ch[i].getElementsByTagName('li');
			for(var j=0; j<items.length; j++){
				if(items[j].getElementsByTagName('li').length){
					Common.Event.add(items[j], 'click', f);
					if(Common.Class.match(items[j], 'selected')){
						ch2=items[j].childNodes;
						for(var k=0; k<ch2.length; k++){
							if(ch2[k].nodeType == 1 && ch2[k].nodeName == 'DIV'){
								Common.Event.add(ch2[k], 'mouseover', f);
								Common.Event.add(ch2[k], 'mouseout', f);
								console.log('selected node',ch2[k])
								// возможность закрытия если кликнуть по <span>
								var selectedNode = ch2[k];
								if(!selectedNode.evented){
									Common.Event.add(selectedNode, 'click', function(evt){
										Common.Event.normalize(evt);
										var target = evt.target || this;
//										document.title = [target.parentNode.className,target.tagName];
										if(target.tagName == 'SPAN' && Common.Class.match(target.parentNode, 'expanded')){
											console.log('try to close', target, target.parentNode.className)
											me.collapseMenu(evt);
											me.collapseForce(evt);
											Common.Event.cancel(evt);
										}
									});
								}
								break;
							}
						}
					}
				}
			}
		}
	}
};

/**
 * Event dispatcher
 * @param {Event} evt
 */
vtb24.menu.prototype.dispatchEvent=function(evt){
	if((evt=Common.Event.normalize(evt))){
		switch(evt.type){
			case 'click':
				this.onClick(evt);
				break;
			case 'mouseover':
				this.onMouseOver(evt);
				break;
			case 'mouseout':
				this.onMouseOut(evt);
				break;
		}
	}
};

/**
 * Expand menu for current menu item
 * @param {Element} elem Menu item
 */
vtb24.menu.prototype.expand=function(elem){
	var em=als.getEmHeight();
	var container=this._getMenuContainer(elem);
	//container.style.height=(container.offsetHeight/em)+'em';
	//container.style.height=(container.offsetHeight)+'px';
	this.setExpandedMenu(container);
	
	
	var prev, next;
	this._setExpandedStateForItem(elem, true);
	
	
	//для первого и последнего пункта выставляю соответствующие классы
	//здесь я всегда уверен, что container.childNodes - это всегда набор li элементов
	var first = container.childNodes[0];
	Common.Class.add(first, 'first');
	Common.Class.add(container.childNodes[container.childNodes.length-1], 'last');

	var _menu = this;
	//событие закрытия меню
	if(!first.evented){

		first.evented = true;
		first.toggle = false;
//		if(document.all){ first.toggle = true; }
		first.unselectable = "on";
		Common.Event.add(first, 'click', function(evt) {
			if (Common.Event.normalize(evt)) {
				first.toggle = !first.toggle;
				var layerX = evt.layerX | evt.offsetX;
				var diff = evt.target.offsetWidth - layerX;
				var target = evt.target || this;

				console.log('first click', target, target.nodeType)

				var isSpan = target.tagName == "SPAN";
				var isA = target.tagName == "A";
				// if(Common.Class.match(target.parentNode, 'expanded')){
				var thisdate = new Date();
//				document.title = [thisdate.getMinutes(), Common.Class.match(target.parentNode, 'expanded'), isSpan]
				if (diff && (diff <= 50 || (Common.Class.match(target.parentNode, 'expanded') && isSpan)) && (isSpan || isA)) {
//					document.title += ' - collapsing';
					_menu.collapseMenu(evt);
					_menu.collapseForce(evt);
					// прекращаем событие
					Common.Event.cancel(evt);
				}
				if(!Common.Class.match(target.parentNode, 'expanded') && isSpan /*&& document.all*/){
//					document.title += ' - expanding'
					Common.Class.add(target.parentNode, 'expanded');
					var nodeToExpand = isSpan ? target.parentNode : target;
					console.log("nodeToExpand",nodeToExpand)
					_menu.expand(target.parentNode.parentNode);
					Common.Event.cancel(evt);
				}
//				if(isSpan && Common.Class.match(target.parentNode, 'expanded')){
//					_menu.collapseMenu(evt);
//					_menu.collapseForce(evt);
//					Common.Event.cancel(evt);
//				}
			}
		});
	}


	Common.Event.add(first, 'mousemove', function(evt) {
		if (Common.Event.normalize(evt)) {
			var layerX = evt.layerX | evt.offsetX;
			var diff = evt.target.offsetWidth - layerX;
			var target = evt.target || this;

			if (diff && diff <= 30 && (target.tagName == "SPAN" || target.tagName == "A")) {
				target.title = Environment.labels.hideMe;
			}
			else{
				target.title = "";
			}
		}
	});
	
	
	//временно скрываю все подменю для того, что точно определеить размеры текущего элемента меню
	//Common.Class.add(elem, 'make-pos');
	
	//reposition siblings
	prev=elem;
	while((prev=prev.previousSibling)){
		this._setExpandedStateForItem(prev, true);
		next=prev.nextSibling;
		//prev.style.top=((next.offsetTop-prev.offsetHeight)/em)+'em';
		prev.style.top=(next.offsetTop-prev.offsetHeight + 1)+'px';
	}
	
	
	var initial_offset=0;
	var ch=elem.childNodes;
	for(var i=0; i<ch.length; i++){
		if(ch[i].nodeType == 1 && ch[i].nodeName == 'DIV'){
			initial_offset=ch[i].offsetHeight + ch[i].offsetTop;
			break;
		}
	}
	
	if((next=elem.nextSibling)){
		this._setExpandedStateForItem(next, true);
		next.style.top=initial_offset - 1 +'px';
		
		while((next=next.nextSibling)){
			this._setExpandedStateForItem(next, true);
			prev=next.previousSibling;
			//next.style.top=((prev.offsetHeight+prev.offsetTop)/em)+'em';
			next.style.top=(prev.offsetHeight - 1 +prev.offsetTop)+'px';
		}
	}
	//Common.Class.remove(elem, 'make-pos');
};

/**
 * Дополнительное скрытие.
 */
vtb24.menu.prototype.collapseForce=function(evt){
	var expandRemove = function(element) {
		if (Common.Class.match(element, "expanded")) {
			Common.Class.remove(element, "expanded");
		}
	};
	var siteMenuNode = document.getElementById("site-menu");
	menu(siteMenuNode.getElementsByTagName("ul") , expandRemove);
	menu(siteMenuNode.getElementsByTagName("li") , expandRemove);
	menu(siteMenuNode.getElementsByTagName("div"), expandRemove);
};

/**
 * Collapse menu
 * @param {Element} elem Menu container or item
 */
vtb24.menu.prototype.collapse=function(elem){
	var container=this._getMenuContainer(elem);
	if(container){
		Common.Class.remove(container, 'expanded');
		var ch=container.childNodes;
		for(var i=0; i<ch.length; i++){
			this._setExpandedStateForItem(ch[i], false);
		}
		Common.Class.remove(container.childNodes[0], 'first');
		Common.Class.remove(container.childNodes[container.childNodes.length-1], 'last');
		container.style.height='auto';
	}
};

/**
 * Set expanded state for menu item
 * @type {Element} elem
 */
vtb24.menu.prototype._setExpandedStateForItem=function(elem, state){
	if(state)
		Common.Class.add(elem, 'expanded');
	else
		Common.Class.remove(elem, 'expanded');
	
	var ch=elem.childNodes, item;
	var il=ch.length;
	for(var i=0; i<il; i++){
		item=ch[i];
		if(item.nodeType == 1 && item.nodeName == 'DIV'){
			if(state)
				Common.Class.add(item, 'expanded');
			else
				Common.Class.remove(item, 'expanded');
			break;
		}
	}
	this._lastItem = item;
};

/**
 * Get menu container for current menu item
 * @param {Element} elem Menu item
 * @return {Element}
 */
vtb24.menu.prototype._getMenuContainer=function(elem){
	return this._findItem(elem, 'ul');
};

/**
 * Get menu item for element
 * @param {Element} elem Menu node
 * @return {Element}
 */
vtb24.menu.prototype._getMenuItem=function(elem){
	return this._findItem(elem, 'li');
};

/**
 * Get menu item label for element
 * @param {Element} elem Menu node
 * @return {Element}
 */
vtb24.menu.prototype._getMenuItemLabel=function(elem){
	return this._findItem(elem, 'div');
};

/**
 * Find specific item in menu
 * @param {Element} elem Menu node
 * @param {String} tag Tag name to find
 * @return {Element}
 */
vtb24.menu.prototype._findItem=function(elem, tag){
	tag=tag.toUpperCase();
	var cont=this.getContainer();
	var _elem=elem;
	var found=false;
	do{
		if(_elem.nodeType == 1 && _elem.nodeName == tag){
			found=true;
			break;
		}
	}while((_elem=_elem.parentNode) && _elem != cont);
	
	return (found) ? _elem : null;
};

/**
 * onClick event handler
 * @param {Event} evt
 */
vtb24.menu.prototype.onClick=function(evt){
	var elem = evt.target;
	if(this.tagName && !evt.target){
		elem = this;
	}
	if(elem.parentNode){
		Common.Class.remove(elem.parentNode, 'hover');
	}
//	alert(elem.tagName)
//	var f = function(){ Common.Class.remove(elem, 'hover'); };
//	setTimeout(f, 10);
	if(elem && elem.tagName){ Common.Class.remove(elem, 'hover'); } // HACK IE, Opera bug fixed

	var exp_menu=this.getExpandedMenu();
	var current_menu=this._getMenuContainer(evt.target);
	
	if(this._findItem(evt.target, 'a')){
		this.dontCollapse=true;
		return;
	}
	
	if(Common.Class.match(current_menu, 'opened'))
		return;
	
	//find if we clicked on subsection
	var subs=this._findItem(evt.target, 'div');
	if(subs && Common.Class.match(subs, 'section'))
		return;
	
	if(exp_menu != current_menu){
		var item=this._getMenuItem(evt.target);
		this.lastClickedItem = item;
		this.expand(item);
		return Common.Event.cancel(evt);
	}
	else{
		this.lastClickedItem = false;
		this.setExpandedMenu(null);
	}
};

vtb24.menu.prototype.onResize=function(evt){
	/* Make an exception for debug */
	//cccc = null;
	//ccc.xxx = null; // Exception here
	
	if (this.lastClickedItem) {
		this.expand(this.lastClickedItem);
	}
};

vtb24.menu.prototype.collapseLastExpanded=function(evt){
	if(this.dontCollapse || this._findItem(evt.target, 'a'))
			return;
	var exp_menu=this.getExpandedMenu();
	if(exp_menu){
			this.collapse(exp_menu);
			this.setExpandedMenu(null);
	}
};
vtb24.menu.prototype.collapseMenu=function(evt){
	var exp_menu = this.getExpandedMenu();
	if(exp_menu){
			this.collapse(exp_menu);
			this.setExpandedMenu(null);
	}
};

vtb24.menu.prototype.onMouseOver=function(evt){
	var item=this._getMenuItemLabel(evt.target);
	if(item && !Common.Class.match(item, 'expanded')){
		Common.Class.add(item, 'hover');
	}
};

vtb24.menu.prototype.onMouseOut=function(evt){
	var item=this._getMenuItemLabel(evt.target);
	if(item)
		Common.Class.remove(item, 'hover');
};

/**
 * Clean up menu element from unneeded text nodes
 * @param {Object} elem
 */
vtb24.menu.prototype._cleanUp=function(elem){
	var ch=elem.childNodes;
	var il=ch.length;
	for(var i=il-1; i>=0; i--){
		if(ch[i].nodeType == 3){
			ch[i].parentNode.removeChild(ch[i]);
		}
	}
};