/* (C) 2009-present Eshkol Institute. All rights reserved.
 *
 * This script file is dealing with menu/submenu logic.
 *
 * Author: Ben Barkay
 * Version: 1.0
 */

// Configure the menus once page has finished loading.
EventManager.addEventHandler(window, 'load', function() {
    MenuManager.configureMenus(null);
});

// Define the MenuManager package object.
var MenuManager = new Object();

/**
 * A static function that configures menus recursively.
 * 
 * @param currentNode   The node to begin searching for menu items from. If not
 *                      specified, this method uses the node which id is
 *                      "navigation" instead.
 */
MenuManager.configureMenus = function(currentNode) {
    // If a node was not given as a parameter, call this method again starting
    // from the navigation.
    if(currentNode == null) {
        return MenuManager.configureMenus(document.getElementById('navigation'));
    }
    
    // Check if this is a link node. If so, validate it has got a sub menu and
    // return the result.
    if(currentNode.tagName && currentNode.tagName.toLowerCase() == 'a') {
        // Get the node's hyper reference target.
        var nodeHyperReference = currentNode.getAttribute('href', 2);
        
        // Check if the node is linking to an ID.
        if(nodeHyperReference && nodeHyperReference.length > 1
            && nodeHyperReference.substring(0,1) == '#') {
            // Create a new expandable menu instance.
            new MenuManager.ExpandableMenu(currentNode,
                nodeHyperReference.substring(1));
            
            // We managed to configure this one expandable menu.
            return 1;
        }
        
        // This is not a link that's serving a sub menu.
        // Though, it should be closing any open sub menu upon mouse hover.
        currentNode.onmouseover = function() {
            // Check if a menu is currently open. If so, close it.
            if(MenuManager.currentOpenedMenu) {
                MenuManager.currentOpenedMenu.close();
            }
        };
        
        return 0;
    }
    
    // This is not a link node, go through its childs -- if any.
    var count = 0;
    for(var i = 0; i < currentNode.childNodes.length; i ++) {
        count += MenuManager.configureMenus(currentNode.childNodes[i]);
    }
    
    // Return the amount of links configured within this node.
    return count;
};

/**
 * A constructor for the expandable menu.
 */
MenuManager.ExpandableMenu = function(openerNode, submenuId) {
    // Set the instance values.
    this.openerNode = openerNode;
    this.submenuNode = document.getElementById(submenuId);
    
    // Add is to the menu manager menus.
    MenuManager[submenuId] = this;
    
    // Set the menu to open on mouse over.
    this.openerNode.onmouseover = function() {
        MenuManager[submenuId].open();
    };
    
    // Point the onclick event function to return false.
    this.openerNode.onclick = falsify;
    
    // Set submenu's position to absolute. The position of the submenu will be
    // configured each time the menu is to be opened. This practice is performed
    // since right now the submenu is hidden and dimensions are unavailable.
    // Maybe in the future this method is to be improved and configuration will
    // complete upon initialization.
    this.submenuNode.style.position = 'absolute';
    
    // Get the menu opener's position and dimensions.
    var pos = Canvas.getPosition(this.openerNode);
    var dim = Canvas.getDimensions(this.openerNode);
    
    // Initialize the cursor
    this.cursor = document.createElement('DIV');
    this.cursor.style.width = dim.getWidth() + 'px';
    this.cursor.style.height = '10px';
    this.cursor.style.position = 'absolute';
    this.cursor.style.left = pos.getX() + 'px';
    this.cursor.style.top = (pos.getY() + dim.getHeight()) + 'px';
    this.cursor.style.backgroundImage = 'url(data/sprites/downarrow.png)';
    this.cursor.style.backgroundRepeat = 'no-repeat';
    this.cursor.style.backgroundPosition = 'center';
    this.cursor.style.display = 'none';
    
    // Append the cursor to the document.
    document.body.appendChild(this.cursor);
};

/**
 * Closes any currently opened menu, and opens this one.
 */
MenuManager.ExpandableMenu.prototype.open = function() {
    // Close the currently opened menu first, if any.
    if(MenuManager.currentOpenedMenu) {
        MenuManager.currentOpenedMenu.close();
    }
    
    // Set the currently opened menu to this one.
    MenuManager.currentOpenedMenu = this;
    
    // Show the submenu.
    this.submenuNode.style.display = 'block';
    this.cursor.style.display = 'block';
    
    // Gather information for calculating the submenu's position.
    var openerPos = Canvas.getPosition(this.openerNode);
    var openerDim = Canvas.getDimensions(this.openerNode);
    var subDim = Canvas.getDimensions(this.submenuNode);
    var wrapPos = Canvas.getPosition(document.getElementById('wrapper'));
    var wrapDim = Canvas.getDimensions(document.getElementById('wrapper'));
    
    // Calculate the opener's center X.
    var openerCenter = openerPos.getX() + (openerDim.getWidth() / 2);
    
    // Calculate submenu optimal X position.
    var submenuX = (openerCenter - (subDim.getWidth() / 2));
    
    // Calculate boundaries.
    var boundaryLeft = wrapPos.getX();
    var boundaryRight = boundaryLeft + wrapDim.getWidth();
    
    // Check if the submenu is exceeding the left boundary.
    if(submenuX < boundaryLeft) {
        submenuX += boundaryLeft - submenuX;
    }
    
    // Check if the submenu is exceeding the right boundary.
    // We are checking them saparately, and the right boundary is the last check
    // to be done by choice, since there can be a case where the menu is too big
    // to be contained within the boundaries. I rather the menu exceed the left
    // boundary instead of the right boundary -- That's why I check it last to
    // make sure it always meets the right boundary requirements.
    if((submenuX + subDim.getWidth()) > boundaryRight) {
        submenuX -= ((submenuX + subDim.getWidth()) - boundaryRight);
    }
    
    // Configure the submenu's location.
    this.submenuNode.style.left = submenuX + 'px';
};

/**
 * Closes this menu.
 */
MenuManager.ExpandableMenu.prototype.close = function() {
    // Hide the submenu.
    this.submenuNode.style.display = 'none';
    this.cursor.style.display = 'none';
    
    // If we are configured as the currently opened sub menu, delete us from
    // opened menu configuration.
    if(MenuManager.currentOpenedMenu == this) {
        delete MenuManager.currentOpenedMenu;
    }
}

// Declare the expandable menu's variables.
MenuManager.ExpandableMenu.prototype.openerNode = null;
MenuManager.ExpandableMenu.prototype.submenuNode = null;
MenuManager.ExpandableMenu.prototype.cursor = null;

