/**
 * @author alu
 */

var FloatMenu = {};

FloatMenu.menuClassName = "FloatMenuClass";
FloatMenu.menuObjects = [];
FloatMenu.menuOptions = [];

// ==== TOOLTIP CLASS ==== //
FloatMenu.Tooltip = function(){
	this.text;
	this.id = -1;
	this.element = null;
	this.opacity = 100;
	this.fadeTimer;
	this.fadeState = 0; // 0 - none , 1 - fading in , 2 - fading out
}

// ==== FADES ELEMENT TO THE TARGET OPACITY ==== //
FloatMenu.Tooltip.prototype.fadeTo = function( opacity , step ){
	var opacityStep = step;
	if( this.opacity > opacity ){
		opacityStep = -step;
	}

	if( opacityStep < 0){
		if( this.opacity+opacityStep > opacity ){
			this.setOpacity(this.opacity+opacityStep);
		}else{
			this.setOpacity(opacity);
			this.setFadeState(0);
		}
	}else{
		if( this.opacity+opacityStep < opacity ){
			this.setOpacity(this.opacity+opacityStep);
		}else{
			this.setOpacity(opacity);
			this.setFadeState(0);
		}
	}
	
	// Repeat moveToXY if destination is not reached
	if( this.fadeState != 0 ){
		
		var self = this;
		var anonymousFade = function(){
			self.fadeTo( opacity , step );
		}
		this.fadeTimer = setTimeout(anonymousFade, 1000/36);
	}
	
	if( this.opacity == 0 ){
		this.element.style.display = 'none';
	}else{
		this.element.style.display = 'block';
	}
}
// ============================================= //

FloatMenu.Tooltip.prototype.setOpacity = function(opacity){
	this.opacity = opacity;
	if( this.element != null ){
		this.element.style.opacity = opacity/100;
		this.element.style.filter = "alpha(opacity=" + opacity + ")";
	}
}

FloatMenu.Tooltip.prototype.setFadeState = function(state){
	this.fadeState = state;
}

FloatMenu.Tooltip.prototype.setText = function(text){
	this.text = text;
}

FloatMenu.Tooltip.prototype.setElement = function(element){
	this.element = element;
}

FloatMenu.Tooltip.prototype.setId = function(id){
	this.id = id;
}
// ======================= //

// ==== TILE CLASS ==== //
FloatMenu.MenuElement = function(){
	this.id = -1; 					// Place in a menu starting from zero.
	this.ownerId = -1; 				// Menu (container) index in FloatMenu.menuObjects
	this.element = null;			// <li> element
	this.width = 0;
	this.height = 0;
	this.xcoord = 0;				// represents style.left
	this.ycoord = 0;				// represents style.top
	this.defaultX = 0;				
	this.defaultY = 0;
	this.tooltip;
	this.timer;						// used to stop animation with clearTimout(timer)
	this.movingState = 0;			// 0 - default position, 
									// 1 - mouseOver movement , 
									// 2 - mouseOut movement, 
									// 3 - element is clicked
}

FloatMenu.MenuElement.prototype.setTooltip = function( tooltip ){
	this.tooltip = tooltip;
}

FloatMenu.MenuElement.prototype.setId = function( id ){
	this.id = id;
}

FloatMenu.MenuElement.prototype.setOwnerId = function( ownerId ){
	this.ownerId = ownerId;
}

FloatMenu.MenuElement.prototype.setDefaultPosition = function( defaultX , defaultY ){
	this.defaultX = defaultX;
	this.defaultY = defaultY;
}

FloatMenu.MenuElement.prototype.setElement = function( element ){
	this.element = element;
}

FloatMenu.MenuElement.prototype.setPosition = function (x , y){
	this.xcoord = x;
	this.ycoord = y;
	if( this.element != null ){
		this.element.style.left = x+'px';
		this.element.style.top = y+'px';
	}
}

FloatMenu.MenuElement.prototype.setSize = function( width , height ){
	this.width = width;
	this.height = height;
	if( this.element != null ){
		this.element.style.width = width+'px';
		this.element.style.height = height+'px';
	}
}

FloatMenu.MenuElement.prototype.attachEventManager = function( event ){
	
	var self = this;
	var anonymousFunction = function(){
		self.manageAnimation( event );
	}
	
	if( this.element.addEventListener ){
		this.element.addEventListener( event , anonymousFunction , false );
	}else if( this.element.attachEvent ){
		this.element.attachEvent( 'on'+event , anonymousFunction );				// Internet Explorer
	}
}

FloatMenu.MenuElement.prototype.manageActiveMenuElement = function(){
	var targetMenu = FloatMenu.menuObjects[this.ownerId];
	var activeMenuElement = null;
	
	// Deactivate another active menu element if it exists
	if( targetMenu.activeElementId >= 0 ){
		activeMenuElement = targetMenu.menuElements[targetMenu.activeElementId];
		
		activeMenuElement.movingState = 0;
		activeMenuElement.moveMenuElement( 2, 100, targetMenu.step);
	}
	
	// Stop animation for clicked element and go to the target position
	clearTimeout(this.timer);
	this.setPosition( this.defaultX+targetMenu.horizontalShift,
	 				  this.defaultY+targetMenu.verticalShift);
	
	clearTimeout(this.tooltip.fadeTimer);
	this.tooltip.setFadeState(2);
	this.tooltip.fadeTo(0, targetMenu.fadeStep );
	
	// Save active element id and set movingState to clicked (3)				  
	targetMenu.activeElementId = this.id;
	this.movingState = 3;
}

FloatMenu.MenuElement.prototype.manageAnimation = function( event ){
	var direction = 0;
	// Shifts element when mouse is over it
	if( event == 'mouseover'){
		direction = 1;
		this.moveMenuElement( direction , 100 , 
							  FloatMenu.menuObjects[this.ownerId].step );
	// Shifts element back if mouse is out
	}else if( event == 'mouseout' ){
		direction = 2;
		this.moveMenuElement( direction, 100 , 
							  FloatMenu.menuObjects[this.ownerId].step);
	// Shows active element if clicked
	}else if( event == 'click'){
		if(FloatMenu.menuObjects[this.ownerId].activeElementMode == 1) {
			this.manageActiveMenuElement();
		}
	}
}

FloatMenu.MenuElement.prototype.moveMenuElement = function( direction, movementPercentage , stepSize ){
	var toX = this.xcoord;
	var toY = this.ycoord;
	var step = stepSize;
	var targetMenu = FloatMenu.menuObjects[this.ownerId];
	if( direction == 1 ){
		if( this.movingState != 1 && this.movingState != 3){
			this.movingState = 1;
			
			clearTimeout(this.timer);
			var toX = this.defaultX+targetMenu.horizontalShift/100*movementPercentage;
			var toY = this.defaultY+targetMenu.verticalShift/100*movementPercentage;
			this.moveToXY(toX,toY,step);
			if( targetMenu.tooltipMode == 1 && this.tooltip){
				clearTimeout(this.tooltip.fadeTimer);
				this.tooltip.setFadeState(1);
				this.tooltip.fadeTo( 100 , targetMenu.fadeStep );
			}
		}
	}else if( direction == 2 && this.movingState != 3){
		if( this.movingState != 2 ){
			this.movingState = 2;
			clearTimeout(this.timer);
			var toX = this.defaultX;
			var toY = this.defaultY;
			this.moveToXY(toX,toY,step);
			if (targetMenu.tooltipMode == 1 && this.tooltip) {
				clearTimeout(this.tooltip.fadeTimer);
				this.tooltip.setFadeState(2);
				this.tooltip.fadeTo(0, targetMenu.fadeStep);
			}
		}
	}
}

FloatMenu.MenuElement.prototype.moveToXY = function( toX , toY , step ){
	var stepY = step;
	var stepX = step;
	
	if( toX < this.xcoord ){
		stepX = -step;
	}
	
	if( toY < this.ycoord ){
		stepY = -step;
	}
	
	var directionX = step/stepX;
	var directionY = step/stepY;

	// Moves menu element to its destination
	if( directionX*(this.xcoord+stepX) < Math.abs(toX) && directionY*(this.ycoord+stepY) < Math.abs(toY)){
		this.setPosition(this.xcoord+stepX,this.ycoord+stepY);
	}else if( directionX*(this.xcoord+stepX) < Math.abs(toX) && directionY*(this.ycoord+stepY) >= Math.abs(toY) ){
		this.setPosition(this.xcoord+stepX, toY);
	}else if( directionX*(this.xcoord+stepX) >= Math.abs(toX) && directionY*(this.ycoord+stepY) < Math.abs(toY) ){
		this.setPosition( toX , this.ycoord+stepY);
	}else if( directionX*(this.xcoord+stepX) >= Math.abs(toX) && directionY*(this.ycoord+stepY) >= Math.abs(toY) ){
		this.setPosition( toX , toY );
		this.movingState = 0; // Indicate that destination is reached
	}

	// Repeat moveToXY if destination is not reached
	if( this.movingState != 0 ){
		var self = this;
		var anonymousMove = function(){
			if( FloatMenu.menuObjects[self.ownerId].speedupMode == 1 ){
				self.moveToXY(toX,toY,step+1/(step*2));	
			}else{
				self.moveToXY(toX,toY,step);	
			}
		}
		this.timer = setTimeout(anonymousMove, 1000/36);
	}
}
// ==================== //

// ==== MENU CLASS ==== //
FloatMenu.Menu = function(){
	this.id = -1;
	this.element = null;
	this.xcoord = 0;
	this.ycoord = 0;
	this.horizontalShift = 0;		// horizontal and vertical shifts from default position // 
	this.verticalShift = 0;			// (used with menu element when moving)                 //
	this.gap = 0;
	this.elementWidth = 0;
	this.elementHeight = 0;
	this.activeElementId = -1;
	this.width = -1;
	this.menuElements = [];
	this.tooltipMode = 0;
	this.fadeStep = 10;
	this.step = 1; 					// increment size when moving menu element
	this.activeElementMode = 0;	    // active element showing mode: 1 - on , 0 - off
	this.speedupMode = 0; 			// accelerate movement: 1 - on , 0 - off
}

FloatMenu.Menu.prototype.setFadeStep = function( step ){
	this.fadeStep = step;
}

FloatMenu.Menu.prototype.setElement = function( element ){
	this.element = element;
}

FloatMenu.Menu.prototype.setId = function ( id ){
	this.id = id;
}

FloatMenu.Menu.prototype.setGap = function( gap ){
	this.gap = gap;
}

FloatMenu.Menu.prototype.setElementSize = function( width , height ){
	this.elementWidth = width;
	this.elementHeight = height;
}

FloatMenu.Menu.prototype.setStep = function( step ){
	this.step = step;
}

FloatMenu.Menu.prototype.setShifts = function( horizontalShift , verticalShift ){
	this.horizontalShift = horizontalShift;
	this.verticalShift = verticalShift;
}

FloatMenu.Menu.prototype.setActiveElementMode = function( mode ){
	this.activeElementMode = mode;
}

FloatMenu.Menu.prototype.setSpeedupMode = function( mode ){
	this.speedupMode = mode;
}

FloatMenu.Menu.prototype.setActiveElementId = function( id ){
	this.activeElementId = id;
}

FloatMenu.Menu.prototype.setWidth = function( width ){
	this.width = width;
	if( this.element != null ){
		this.element.style.width = width+'px';
	}
}

FloatMenu.Menu.prototype.setTooltipMode = function( mode ){
	this.tooltipMode = mode;
}

FloatMenu.Menu.prototype.addMenuElement = function( menuElement ){
	menuElement.setId(this.menuElements.length);
	menuElement.setOwnerId(this.id);
	this.menuElements.push(menuElement);
}

FloatMenu.Menu.prototype.createMenu = function(){
	var listElements = this.element.getElementsByTagName('li');
	var currentElement;
	var menuElement = null;
	var tooltipText;
	var tooltipElement;
	var tooltipObject;
	var imageElement;
	var textNode;
	for( var i=0 ; i < listElements.length ; i++ ){
		currentElement = listElements[i];
		
		menuElement = new FloatMenu.MenuElement();
		menuElement.setElement(currentElement);
		menuElement.element.style.position = 'relative';
		menuElement.element.style.cssFloat = 'left';
		menuElement.element.style.styleFloat = 'left'; 			// For Internet Explorer
		menuElement.setSize( this.elementWidth , 
							 this.elementHeight);
		if( i+1 < listElements.length ){
			menuElement.element.style.marginRight = this.gap+'px';
		}
		menuElement.setDefaultPosition( 0 , 0 );
		
		// Check if tooptip mode is on and seearch for images to add a tooltip
		if( this.tooltipMode == 1){
			imageElement = menuElement.element.getElementsByTagName('img')[0];
			tooltipText = imageElement.getAttribute('fmTooltip');
			if( tooltipText ){
				tooltipElement = document.createElement('div');
				tooltipObject = new FloatMenu.Tooltip();
				tooltipObject.setText(tooltipText);
				textNode = document.createTextNode(tooltipText);
				tooltipElement.appendChild(textNode);
				tooltipObject.setElement(tooltipElement);
				tooltipObject.element.style.position = 'absolute';
				tooltipObject.element.style.zIndex = listElements.length-i;
				tooltipObject.element.setAttribute('class','FMTooltipClass');
				menuElement.element.appendChild(tooltipObject.element);
				menuElement.setTooltip(tooltipObject);
				menuElement.tooltip.setOpacity(0);
			}
		}
		
		// Attach events
		menuElement.attachEventManager( 'mouseover' );
		menuElement.attachEventManager( 'mouseout' );
		menuElement.attachEventManager( 'click' );
		
		this.addMenuElement(menuElement);	
	}
	
	if( this.width < 0 ){
		this.element.style.width = this.menuElements.length*this.elementWidth+
								  	  (this.gap*(this.menuElements.length-1))+'px';
	}else{
		if( this.menuWidth != 0 ){
			this.element.style.height = Math.ceil(this.menuElements.length*this.elementWidth/this.width)*
										this.elementHeight+'px';
		}
	}
	
}
// ==================== //

// ==== GET ELEMENTS BY CLASS NAME ==== //
FloatMenu.getElementsByClass = function ( className ){
    var node = document.getElementsByTagName('body')[0];
    var nodeElements = node.getElementsByTagName('*');
    var elementsArray = [];
	var currentElement;
    
    for( var i = 0 ; i < nodeElements.length ; i++ )
    {
		currentElement = nodeElements[i];
        if( currentElement.className == className )
        {
            elementsArray.push( currentElement );
        } 
    }
    
    if( elementsArray.length == 0 )
    {
        return null;
    }

    return elementsArray;
    
}
// ==================================== //

// ==== FINDS 'FloatMenuClass' ELEMENTS AND CREATES MENU OBJECTS ==== //
FloatMenu.findMenus = function(){
	var menus = FloatMenu.getElementsByClass( FloatMenu.menuClassName );
	var createdMenus = [];
	var menu = null;
	var currentMenuElement;
	for( var i=0 ; i<menus.length ; i++ ){
		currentMenuElement = menus[i];
		
		menu = new FloatMenu.Menu();
		menu.setElement(currentMenuElement);
		menu.setId(i);
		createdMenus.push(menu);
	}
	
	if( createdMenus.length == 0 ){
		return null;
	}

	return createdMenus;
}
// ================================================================== //

// ==== CREATE MENU OBJECT FOR EACH FOUND MENU ELEMENT ==== //
FloatMenu.createMenus = function(){
	for( var i=0 ; i< FloatMenu.menuObjects.length ; i++ ){
		FloatMenu.menuObjects[i].createMenu();
	}
}
// ======================================================== //

// ==== PREPARE ALL MENUS (USING GIVEN OPTIONS) ==== //
FloatMenu.prepareMenus = function( menuArray ){
	var currentOptions;
	var currentMenuId;
	var currentMenu;
	for( var i=0 ; i<menuArray.length ; i++){
		
		currentMenu = menuArray[i];
		currentMenuId = currentMenu.element.getAttribute('id');
		currentOptions = FloatMenu.getOptions(currentMenuId);
		
		// ==== SET ELEMENT SIZE ==== //
		if( currentOptions.elWidth ){
			currentMenu.setElementSize(currentOptions.elWidth,
									   currentMenu.elementHeight);
		}
		if( currentOptions.elHeight ){
			currentMenu.setElementSize( currentMenu.elementWidth , 
										currentOptions.elHeight);
		}
		// ========================== //
		
		// ==== SET SHIFTS ==== //
		if( currentOptions.hShift ){
			currentMenu.setShifts(currentOptions.hShift,
								  currentMenu.verticalShift);
		}
		if( currentOptions.vShift ){
			currentMenu.setShifts(currentMenu.horizontalShift,
								  currentOptions.vShift);
		}
		// ==================== //
		
		// ==== SET STEP SIZE ==== //
		if( currentOptions.step && currentOptions.step > 0){
			currentMenu.setStep( currentOptions.step );
		}
		// ======================= //
		
		// ==== SET GAP SIZE ==== //
		if( currentOptions.gap && currentOptions.gap >= 0 ){
			currentMenu.setGap( currentOptions.gap );
		}
		// ====================== //
		
		// ==== SET MENU WIDTH ==== //
		if (currentOptions.menuWidth && currentOptions.menuWidth >= 0) {
			currentMenu.setWidth(currentOptions.menuWidth);
		}
		// ======================== //

		// ==== SET ACCELERATION ==== //
		if( currentOptions.speedup && currentOptions.speedup >= 0 && currentOptions.speedup < 2){
			currentMenu.setSpeedupMode( currentOptions.speedup );
		}
		// ========================== //
		
		// ==== SET DISPLAY ACTIVE ==== //
		if( currentOptions.active && currentOptions.active >= 0 && currentOptions.active < 2){
			currentMenu.setActiveElementMode(currentOptions.active);
		}
		// ============================ //
		
		// ==== SET DISPLAY ACTIVE ==== //
		if( currentOptions.tooltip && currentOptions.tooltip >= 0 && currentOptions.tooltip < 2){
			currentMenu.setTooltipMode(currentOptions.tooltip);
		}
		// ============================ //
		
		// ==== SET FADE STEP ==== //
		if( currentOptions.fadeStep && currentOptions.fadeStep > 0){
			currentMenu.setFadeStep(currentOptions.fadeStep);
		}
		// ============================ //
		
		currentMenu.element.style.height = currentMenu.elementHeight+'px';
		currentMenu.element.style.listStyle = 'none';
		currentMenu.element.style.listStyleImage = 'none';
	}
}

FloatMenu.setOptions = function( menuId , options ){
	if( menuId && options ){
		var tempArray = [menuId,options];
		FloatMenu.menuOptions.push(tempArray);
	}
}

FloatMenu.getOptions = function( menuId ){
	for( var i=0 ; i<FloatMenu.menuOptions.length ; i++){
		if( FloatMenu.menuOptions[i][0] && FloatMenu.menuOptions[i][0] == menuId ){
			return FloatMenu.menuOptions[i][1];
		}
	}
}

// ==== Creates all menus when page is loaded ===== //
FloatMenu.addOnLoadEvent = function(){
	var self = this;
	var anonymousFunction = function(){
		self.menuObjects = self.findMenus();
		self.prepareMenus(self.menuObjects);
		self.createMenus();
	}
	
	if( window.addEventListener ){
		window.addEventListener('load', anonymousFunction, false);
	}else if( window.attachEvent ){
		window.attachEvent('onload', anonymousFunction);
	}
}
// ================================================= //

FloatMenu.addOnLoadEvent();

