/*****************************************************************************
 * menu.js
 *
 * Author: Cory Kim
 *
 * Purpose:
 * This script generates the industry/application fast-walk script.
 * It relies on a previously generated set of menu nodes in the form of a JS
 * file (see ../data/menu-1000001.js) which should set the menuNodes variable.
 *
 *****************************************************************************/

/**
 * hashtable of menu nodes built up from menu-XXXXXX.js files
 */
var menuNodes = {};

/**
 *  constants
 */
var SUBPANEL_ID_PREFIX     = 'subpanel';
var MENU_ID_PREFIX         = 'menu';
var PANEL_ID_SUFFIX        = 'panel';
var MENU_CONTAINER_ID      = 'navigation';
var APPLICATION_TARGET_URL = '/'; // override with $AJAX_URL for application target component

// CKIM: added this variable
var APPLICATION_AJAX_RECEIVER; // assign to the element that should receive the AJAX response

/**
 * Initializes a navigation panel and all submenus.
 *
 * @param panel  - the panel to initialize
 * @param isRoot - whether this menu is a root menu
 */                                                     
function initNavMenu(panel, isRoot)
{
  if (!isRoot)
  {
    panel.id = panel.parentNode.parentNode.id + PANEL_ID_SUFFIX;
    panel.style.visibility = 'hidden';
  }

  // CKIM: toggle nav menus when panels are clicked also
  panel.onclick = toggleNavMenu;

  var menus = panel.getElementsByTagName('ul');

  for (var i=0; i < menus.length; i++)
  {
    menus[i].onclick = toggleNavMenu;

    menus[i].onmouseout = function(){
      if (this.className == 'hover') this.className = '';
    };
    menus[i].onmouseover = function(){
      if (this.className == '') this.className = 'hover';
    };

    var divs = menus[i].getElementsByTagName('div');

    for (var j=0; j<divs.length; j++)
    {
      if (divs[j].className == 'sublabel')
      {
        divs[j].onselectstart = function(){return false;}; // MSIE only
      }
      else if (divs[j].className == 'panel')
      {
        divs[j].id = menus[i].id + PANEL_ID_SUFFIX;
        divs[j].style.visibility = 'hidden';
      }
    }
  }
}

/**
 * On-click event handler for a menu.
 *
 * @param evt - for FireFox, the fired event
 */
function toggleNavMenu(evt)
{
  evt = (evt) ? evt : ((window.event) ? window.event : null);
  var evtTarget = getMenuEventTarget(evt);
  if (evt) evt.cancelBubble = true;

  if (evtTarget && 'A' == evtTarget.tagName) 
  {
    // if I am a top-level menu, hide the other menu items
    var navParent = this.parentNode;
    if (navParent && MENU_CONTAINER_ID == navParent.id)
    {
      var menus = navParent.getElementsByTagName('ul');
      for (var i=0; i < menus.length; i++)
      {
        hideNavMenus(menus[i]);
      }
    }
    return;
  }

  var panel = document.getElementById(this.id + PANEL_ID_SUFFIX);

  if (panel)
  {
    // report the click event on top-level panel objects, which do not trigger
    // AJAX requests.
    if (this.parentNode.id == null || this.parentNode.id == MENU_CONTAINER_ID || this.parentNode.id == '')
    {
      var applicationId = this.id.substring(MENU_ID_PREFIX.length);
      reportClickEvent(applicationId);
    }
  
    // turn off sibling menus

    var menus = this.parentNode.getElementsByTagName('ul');

    for (var i=0; i < menus.length; i++)
    {
      if (this != menus[i] && this.parentNode == menus[i].parentNode)
      {
        hideNavMenus(menus[i]);
      }
    }

    // if menu is hidden, hide child menus too

    var currentMenuVisibility = panel.style.visibility;

    if ('hidden' == currentMenuVisibility)
    {
      toggleNavMenuPanel(this, true);
      if (evtTarget && '2' == evtTarget.getAttribute('level'))
      {      
        var applicationId = evtTarget.getAttribute('_id');
        requestApplicationTarget(applicationId);
      }
    }
    else
    {
      hideNavMenus(this);
    }
  }
  else
  {
    if (evtTarget) loadNavMenu(evtTarget.getAttribute('_id'));
  }
}

/**
 * Loads a navigation hierarchy either from the hash table of menu nodes
 * or (if not present in the hash) from disk.
 *
 * @param id     - the application node id attribute value
 * @param isRoot - whether this is the menu root
 */
function loadNavMenu(id, isRoot)
{
  // test for the presence of the nodes

  var nodes  = menuNodes[id];
  var target = document.getElementById((isRoot) ? MENU_CONTAINER_ID : SUBPANEL_ID_PREFIX+id);
  var panel  = document.createElement('div');

  panel.className = 'panel';

  if (isRoot)
  {
    panel.style.visibility = 'visible';
  }

  for (var i=0; i<nodes.length; i++)
  {
    var nId   = nodes[i].id;
    var nName = nodes[i].name;

    if (nodes[i].leaf || menuNodes[nId] == null || menuNodes[nId].length < 1)
    {
      // <a href="...">nName</a>

      var link = document.createElement('a');
      link.href = "javascript:requestApplicationTarget('" + nId + "');";
      link.appendChild(document.createTextNode(nName));

      panel.appendChild(link);
    }
    else
    {
      // <ul>
      //   <div class="sublabel" _id='nId'>nName</div>
      //   <div class="subpanel" id='menu_nId'></div>
      // </ul>

      var ul       = document.createElement('ul');
      var sublabel = document.createElement('div');
      var subpanel = document.createElement('div');

      sublabel.className = 'sublabel';
      subpanel.className = 'subpanel';

      sublabel.setAttribute('_id', nId);
      if (!isRoot) sublabel.setAttribute('level',2);

      ul.id = MENU_ID_PREFIX + nId;
      subpanel.id = SUBPANEL_ID_PREFIX + nId;

      sublabel.appendChild(document.createTextNode(nName));

      ul.appendChild(sublabel);
      ul.appendChild(subpanel);

      panel.appendChild(ul);
    }
  }

  if (isRoot && target.firstChild)
  {
    target.removeChild(target.firstChild);
  }

  target.appendChild(panel);
  initNavMenu(panel, isRoot);

  if (!isRoot)
  {
    var menu = target.parentNode;
    // invoke the menu's click
    menu.onclick();
  }
}

/**
 * Toggles the visibility of the passed menu.
 *
 * @param menu the target menu to toggle
 * @param isVisible whether the menu should be shown
 */
function toggleNavMenuPanel(menu, isVisible)
{
  menu.className = (isVisible) ? 'clicked' : '';

  var panel = document.getElementById(menu.id + PANEL_ID_SUFFIX);

  if (panel)
  {
    panel.style.visibility = (isVisible) ? 'visible' : 'hidden';
  }
}

/**
 * Hides the passed menu and all submenus.
 *
 * @param menu the menu object to hide
 */
function hideNavMenus(menu)
{
  toggleNavMenuPanel(menu, false);
  var menus = menu.getElementsByTagName('ul');
  for (var i=0; i < menus.length; i++)
  {
    toggleNavMenuPanel(menus[i], false);
  }
  
  // reset the product list to default style
  updateProductListStyle();
}

/**
 * Gets the menu event target.  The target will either be a UL,
 * a div (class=sublabel) or an anchor link.
 *
 * @param event the event whose target should be extracted
 */
function getMenuEventTarget(event)
{
  if (!event) return null;

  var evtTarget = (event.target)
                ? event.target
                : ((event.srcElement) ? event.srcElement : null);

  if (evtTarget && 'UL' == evtTarget.tagName)
  {
    evtTarget = evtTarget.firstChild;
  }

  return evtTarget;
}

/*
function handleApplicationTarget(xmlDoc, text)
{
  var appNode = xmlDoc.documentElement.getElementsByTagName('application-id')[0];

  document.getElementById('applicationTargetId').innerHTML = appNode.firstChild.nodeValue;
  document.getElementById('applicationTarget').style.display = 'inline';
}
*/

// CKIM: replaced the handler function
function handleApplicationTarget(xmlDoc, text)
{
  outputNode = xmlDoc.documentElement;
  writeProductLineList(outputNode);

  var showLink = document.getElementById('show-all-results');

  // update the  "show all" form
  var showForm = document.getElementById('product-lister-form');
  if (showForm != null) {
    var plNodes = xmlDoc.getElementsByTagName('product-line');
    // we show the "show all" if there are more than one product lines to show
    if (plNodes != null && plNodes.length > 1)
    {
      var appElements = xmlDoc.getElementsByTagName('application');
      showForm.application.value = appElements[0].getAttribute('id');
		  // reveal the "show all" link
		  showLink.style.display = 'block';
    }
    else
    {
      // hide the "show all" link
      showLink.style.display = 'none';
    }
  }
  else
  {
    alert('showForm could not be found!');
  }
}


function requestApplicationTarget(id)
{
  var req = new AjaxRequest(APPLICATION_TARGET_URL, handleApplicationTarget);
  // CKIM: changed the parameter
  //req.setParameter('appId', id);
  req.setParameter('application', id);
  req.submit();
  
  // CKIM: for NetTracker
  reportClickEvent(id);          
}



// CKIM: specialized functions follow...
// writes the list of product lines in a Product Line Lister component
function writeProductLineList(xml)
{
  out = APPLICATION_AJAX_RECEIVER;
  out.innerHTML = "";

  if (xml != null)
  {
	  // iterate through the product line tags
	  var plNodes = xml.getElementsByTagName('product-line');
	  
	  // set the appropriate class for the container depending on whether
	  // we have any results
	  if (plNodes != null && plNodes.length > 0)
	  {
	    updateProductListStyle("hasProductLines");
	  }
	  else
	  {
	    updateProductListStyle("noProductLines");
	  }
	  
	  if (plNodes != null)
	  {
		  // we use this template to generate new list items
		  var listItemTemplate = document.getElementById('product-line-item-template');

			var applicationList = xml.getElementsByTagName('application');
		  var applicationNode;
			var applicationId = '';
			
			if (applicationList != null)
			{
			  applicationNode = applicationList[0];
			}
			if (applicationNode != null)
			{
			  applicationId = applicationNode.getAttribute("id");
			}
		  
		  for (var i=0; i<plNodes.length; i++) {
		    var pl = plNodes[i];
		
		    // make a clone of the template
		    var listNode = listItemTemplate.cloneNode(true);
		
		
		    // find the anchor node
		    var anchorNode = locateNode(listNode, 'a', 'id', 'product-line-anchor');
		
		    // workaround for a stupid IE bug, makes sure this is a relative tag
		    if (anchorNode != null) {
		      fixAnchorNode(anchorNode);
		      anchorNode.href += 'product-line=' + pl.getElementsByTagName('id')[0].firstChild.nodeValue;
		      anchorNode.href += '&application=' + applicationId;
		    } else {
		      alert('anchorNode could not be found!');
		    }
		
		    // find the name node
		    var nameNode = locateNode(listNode, 'span', 'id', 'product-line-name');
		    if (nameNode != null) {
		      nameNode.innerHTML = pl.getElementsByTagName('name')[0].firstChild.nodeValue;
		    }
		    else
		    {
		      alert('nameNode could not be found!');
		    }
		
		    // out.appendChild(listNode);
        out.innerHTML = out.innerHTML + '<div>'+listNode.innerHTML+'</div>';
		
		    // the template was hidden, we will un-hide the clone
		    listNode.style.display="block";
	  	}	  
  	}
  }
}



// locates the first sub-node that matches the tag name, attribute=value
function locateNode(parentNode, tagName, attr, value)
{
  var candidates = parentNode.getElementsByTagName(tagName);
  for (var i=0; i<candidates.length; i++) {
    var checkAttr = candidates[i].getAttribute(attr);
    if (checkAttr != null && checkAttr == value) {
      return candidates[i];
    }
  }
}


/*
  In IE6, the XML document that we have has all of its href's set to "about:blank/"
  In IE7, it's "about:" (without blank)
*/
function fixAnchorNode(anchorNode)
{
  anchorNode.href = removeFromLeft(anchorNode.href, 'about:blank');
  anchorNode.href = removeFromLeft(anchorNode.href, 'about:');
}

/*
  If originalString begins with removeString, removeString is removed.
*/
function removeFromLeft(originalString, removeString)
{
  var result;
  var stringIndex = originalString.indexOf(removeString);
  if (stringIndex == 0)
  {
    result = originalString.substring(removeString.length);
  }
  else
  {
    result = originalString;
  }
  
  return result;
}



/*
  Update the style class of the product list; used for highlighting the
  list when product lines are found.
*/
function updateProductListStyle(className)
{
  var defaultClass = "noProductLines";

  if (APPLICATION_AJAX_RECEIVER != null)
  {
    var containerNode = APPLICATION_AJAX_RECEIVER.parentNode;
    if (containerNode != null)
    {
      if (className == null || className == "")
      {
        className = defaultClass;    
      }

      containerNode.className = className;
    }
  }
}


// utility function for getting a query variable
var QUERY_VARIABLES = null;
function getQueryVariable(variable)
{
  if (QUERY_VARIABLES == null)
  {
    var query = window.location.search.substring(1);
    var vars  = query.split("&");
    QUERY_VARIABLES = new Array(vars.length);
    for (var i=0; i<vars.length; i++)
    {
      QUERY_VARIABLES[i] = vars[i].split("=");
    }
  }
  for (var i=0; i<QUERY_VARIABLES.length; i++)
  {
    if (QUERY_VARIABLES[i][0] == variable)
    {
      return QUERY_VARIABLES[i][1];
    }
  }
}


// reports the click event to NetTracker
function reportClickEvent(applicationId)
{
  //debug('reportClickEvent('+applicationId+')');
  if (applicationId != null && applicationId != '')
  {
    var industryId = getQueryVariable('industry');
    var eventString = 'industry='+industryId+'&application='+applicationId;
    debug("Reporting event for '"+eventString+"'");
    ntptEventTag(eventString);
  }
  else
  {
    //debug("reportClickEvent("+applicationId+") yielded no application id");
  }
}

function debug(message)
{
  //console.debug(message);
  //alert(message);
}
