//Turn on MenuUtilsDebug for debugging info. Call muDebug() to dump the debugging data onto screen via document.write().
var MenuUtilsDebug=false;
var MenuUtilsDebugData=[];

//This is used internally only:
function LCRAMenuItem(level, title, url, openInNewWindow){
  this.level=level;
  this.title=title;
  this.url=url;
  this.openInNewWindow=openInNewWindow;
  this.openInParentWindow=false;
}
function muFindMenuItem(itemName, menuItems){
  for (var i=0; i<menuItems.length; i++) 
    if (menuItems[i].url==itemName)
      return i;
  alert("muFindMenuItem: No item found for item \""+itemName+"\" ");
  return 0;
}
function muDebug(msg){
  if (MenuUtilsDebug)
    MenuUtilsDebugData.push(
      //new Date().getTime()+" "+
      msg+"<br/>"
    );
}
function muDebugFlush(){
  if (MenuUtilsDebugData!=null)
    document.write(MenuUtilsDebugData.join(""));
  MenuUtilsDebugData=[];
}

/////////////////////////
//                     //
// LCRATopMenu object: //
//                     //
/////////////////////////


function LCRATopMenu(menuContainer, menuItems, menuStylesArray){
  this.menuContainer=menuContainer;
  this.menuItems=menuItems;
  this.menuStylesArray=menuStylesArray;
  if (menuStylesArray!=null)
    this.maxLevels=menuStylesArray.length;
  this.startBelow=null;
  this.startWith=null;
}
LCRATopMenu.prototype.makeMenus=tmMakeMenus;
LCRATopMenu.prototype.makeMenuContainer=tmMakeMenuContainer;
LCRATopMenu.prototype.makeMenuItem=tmMakeMenuItem;


function tmMakeMenus(){

  //Setup variables:
  var level=1;
  var parentName=null;
  var menuNameSuffix="top";
  var extraMenuItemInfo="";
  var container=this.menuContainer;
  
  //Find starting point:
  var startItem=0;
  if (this.startBelow!=null){
    var sbi=muFindMenuItem(this.startBelow, this.menuItems);
    level=this.menuItems[sbi].level+1;
    startItem=sbi+1;
  }
  if (this.startWith!=null){
    var swi=muFindMenuItem(this.startWith, this.menuItems);
    level=this.menuItems[swi].level;
    startItem=swi;
  }  
  var offset=level-1;
  var maxLevel=this.maxLevels+offset;

  if (this.startWith!=null){
    var rootItem=this.menuItems[startItem];
    this.makeMenuItem(container, rootItem, menuNameSuffix);      
    container=null;
    parentName=rootItem.url;
    level++;
  }
  
  
  //Loop thru the entire array once for each level of menus (Milonic
  //actually forces menus to be created this way; it won't accept
  //an additional level 1 if a level 2 has been added to an existing
  //level 1):
  var found=true;
  while (found){
    found=false;
    var parentLevel=Math.min(maxLevel, level-1);    
    //Loop thru all items finding ones that are the current level:
    for (var i=startItem; i<this.menuItems.length; i++)  {
      var mi=this.menuItems[i];
      if (mi.level==level){
        //Okay this item is at the current level:
        if (container==null)
          container=this.makeMenuContainer(parentName+menuNameSuffix, this.menuStylesArray, level, offset, mi);
        if (level>maxLevel)
          container.aI("url="+mi.url);
        else
          this.makeMenuItem(container, mi, menuNameSuffix);      
        found=true;
        parentName=null;
      }
      else 
      if (mi.level==offset){
        //Stop because we've gone past the end of the items in the 
        //menu, since we're at a lower level than the first item in the
        //menu. We don't need to look for any more items at this level, 
        //but we'll keep going with the outer while loop so we can render 
        //lower-level items.
        break;
      }
      else 
      if (mi.level==offset+1 && this.startWith!=null && i!=startItem){
        //Same as the if statement above, but for when you use startWith
        //instead of startBelow:
        break;
      }
      else
      if (mi.level==parentLevel){
        //This is a parent level. We'll keep track of this parent
        //and use it as the container if the next item in the list
        //is a child. 
        container=null;
        parentName=mi.url;
      }
    }
    level++;
  }
  //This is a milonic invocation:
  drawMenus();
}


function tmMakeMenuContainer(containerName, menuStylesArray, level, offset, mi){
  var offsetLevel=level-offset;
  var styleIndex=offsetLevel-1;
  var c=new menuname(containerName);
  //If we can't find a style for this level, use the lowest one available:
  if (styleIndex>=menuStylesArray.length)
    styleIndex=menuStylesArray.length-1;
  c.style=menuStylesArray[styleIndex];
  c.style.alwaysvisible=1;
  return c;
}
function tmMakeMenuItem(container, item, suffix){
  //muDebug(item.level+" "+item.title);
  var params=[
    "text=", item.title,
    ";url=", item.url,
    ";showmenu=", item.url+suffix
  ];
  if (item.openInNewWindow)
    params.push(";target=_blank");  
  else
  if (item.openInParentWindow)
    params.push(";target=_top");  
  container.aI(params.join(""));
}



/////////////////////////
//                     //
// LCRALeftMenuObject: //
//                     //
/////////////////////////

function LCRALeftMenu(menuItems){
  this.menuItems=menuItems;
  this.depth=0;
  this.startBelow=null;
  this.startWith=null;
  this.currPage=null;
  this.itemStyles=[];
  this.parentStyles=[];
  this.selectedItemStyles=[];
  this.warnOnNoSelection=true;
  this.defaultIndexPages=["index.html"];
}
LCRALeftMenu.prototype.drawMenu=lmDrawMenu;
LCRALeftMenu.prototype.drawItem=lmDrawItem;
LCRALeftMenu.prototype.isParent=lmIsParent;
LCRALeftMenu.prototype.drawItemsBefore=lmDrawItemsBefore;
LCRALeftMenu.prototype.drawItemsAfter=lmDrawItemsAfter;
LCRALeftMenu.prototype.drawMenuItems=lmDrawMenuItems;
LCRALeftMenu.prototype.pageMatch=lmPageMatch;

function lmDrawMenu(){
  //Default depth to length of itemStyles
  //or 1000.
  var depth=this.depth;
  if (depth==0) {
   if (this.itemStyles.length>0)
     depth=this.itemStyles.length;
   else
     depth=1000;
  }
  
  var menuItems=this.menuItems;

  //Find starting point:
  var startItem=0;
  if (this.startBelow!=null)
    startItem=muFindMenuItem(this.startBelow, this.menuItems)+1;
  if (this.startWith!=null)
    startItem=muFindMenuItem(this.startWith, this.menuItems);
  var offset=menuItems[startItem].level-1;
  depth+=offset;

  //Render menu items:
  var drawn=false;
  for (var i=startItem; i<menuItems.length && !drawn; i++){
    if (this.pageMatch(menuItems[i].url, this.currPage)){
      //If this item is too deep, I'm only showing the first parent that
      //is acceptable:
      while (menuItems[i].level>depth && i>startItem)
        i-=1;
      this.drawMenuItems(i, offset, depth);
      drawn=true;
    }
  }  
  
  //If no current page, just draw the top level items and deal with it:
  if (!drawn){
    var level=menuItems[startItem].level;
    for (var i=startItem; i<menuItems.length && !drawn; i++)
      if (menuItems[i].level<=offset)
        break;
      else
      if (menuItems[i].level==level)
        this.drawItem(menuItems[i], true, offset, false);
    //Note that we cut some slack for this.currPage!=this.startBelow... even though
    //one can argue that this is in fact an error, it's understandable that the 
    //intention is to avoid the redundancy of having to specify the "home page" as
    //a menu item:
    if (this.currPage!=null && this.warnOnNoSelection  && !this.pageMatch(this.startBelow, this.currPage)){
      var foo=new LCRAMenuItem(offset+1, "<span style=\"font-size: 8px; font-weight:normal; color:#442222;\">Warning: Could not find menu item for selected page \&quot;"+this.currPage+"&quot;</font>", this.currPage, false);
      this.drawItem(foo, false, offset, false);
    }
  }

}
function lmPageMatch(aPage, currPage){
  if (aPage==null)
    return false;
  if (aPage==currPage)
    return true;
    
  //If we browsed to a directory, we may be looking at the index
  //page, but the browser url doesn't show it, so we'll account
  //for that:
  if (this.defaultIndexPages!=null && aPage.indexOf(currPage)>-1)
    for (i=0; i<this.defaultIndexPages.length; i++)
      if (aPage==currPage+this.defaultIndexPages[i]    || 
          aPage==currPage+"/"+this.defaultIndexPages[i])
        return true;
        
  return false;
}

function lmDrawMenuItems(index, offset, depth){
  var myItem=this.menuItems[index];
  var level=myItem.level;

  //Draw items up thru this one:
  this.drawItemsBefore(index, level, offset, depth);

  //Draw items after this one:
  if (this.isParent(index, depth))
    level+=1;
  this.drawItemsAfter(index, level, offset, depth);
}
function lmDrawItemsBefore(currIndex, level, offset, depth){
  //Build backwards array of indexes of items to render:
  var indexes=new Array();
  for (var i=currIndex; level>offset && i>=0; i--){
    var thisLevel=this.menuItems[i].level;
    if (thisLevel==level)
      indexes.push(i);
    //We want to show the startWith item, but none of the other
    //items at startWith's level, so we stop:
    if (this.startWith!=null && level==offset+1 && this.menuItems[i].url==this.startWith)
      break;
    //If the next item is a level lower, we now want that level
    if (i>0 && this.menuItems[i-1].level==level-1) 
      level--;
  }
  //Loop backwards, rendering as we go:
  for (var j=indexes.length-1; j>=0; j--){
    var index=indexes[j];
    var myItem=this.menuItems[index];
    var isSelected=j==0;
    if (!isSelected){
      var nextItem=this.menuItems[indexes[j-1]];
      isSelected=myItem.level==nextItem.level-1;
    }
    this.drawItem(myItem, this.isParent(index, depth), offset, isSelected);
  }
}
function lmDrawItemsAfter(currIndex, level, offset, depth){
  for (var i=currIndex+1; level>offset && i<this.menuItems.length; i++){
    var myItem=this.menuItems[i];
    var thisLevel=myItem.level;
    //Finished if we reached lower level than root item:
    if (thisLevel<=offset || (this.startWith!=null && thisLevel<=offset+1))
      return;
    if (thisLevel<=level) {
      this.drawItem(myItem, this.isParent(i, depth), offset, false);
      level=thisLevel;
    }
  }
}
function lmIsParent(index, depth){
  var next=index+1;
  var m=this.menuItems;
  return next<m.length && 
         m[next].level>m[index].level && 
         m[next].level<=depth;
}


/////////////////////
// Left Menu HTML: //
/////////////////////

function lmDrawItem(myItem, isParent, offset, isSelected){
  var index=myItem.level-(offset+1);
  var d=document;
  d.write("<div class=\"");  
  if (this.itemStyles.length>index)
    d.write(this.itemStyles[index]);
  if (isParent && this.parentStyles.length>index){
    d.write(" ");  
    d.write(this.parentStyles[index]);
  }
  if (isSelected && this.selectedItemStyles.length>index){
    d.write(" ");
    d.write(this.selectedItemStyles[index]);
  }
  d.write("\"><a href=\"");
  d.write(myItem.url);
  d.write("\"");
  if (myItem.openInNewWindow)
    d.write(' target="_blank"');
  d.write(">");
  d.write(myItem.title);
  d.write("</a></div>");
}


//////////////////////////
//                      //
// XML retrieval stuff: //
//                      //
//////////////////////////

/** 
 * This loads an array of menu data from an XML file. The resulting
 * array can be passed to the contstructors for LCRATopMenu and LCRALeftMenu.
 */
function loadLCRAMenuXML(xmlURL){
  var xmlReq=muOpenXMLRequest(xmlURL);
  var rootie=xmlReq.responseXML.getElementsByTagName("items")[0];
  var menuArray=[];  
  muDescendXML(rootie, menuArray, 0, 0);
  return menuArray;
}

function muDescendXML(myNode, menuArray, nodeLevel, nodeCount){
  nodeCount++;
  //Create item:
  if (myNode.nodeName=="item"){
    menuArray.push(
      new LCRAMenuItem(
        nodeLevel, 
        myNode.getAttribute("title"), 
        myNode.getAttribute("url"), 
        (myNode.getAttribute("openInNewWindow")=="true")
      )
    );
  }
  if (nodeCount>4000){
    alert('overflow');
    return;
  }
  
  //Recurse through child nodes:
  if (myNode.childNodes==null)
    return;  
  for (var x=0; x<myNode.childNodes.length; x++){
    var nextNode=myNode.childNodes.item(x);
    if (nextNode.nodeName=="item")
      muDescendXML(nextNode, menuArray, nodeLevel+1, nodeCount);
  }
}


function muOpenXMLRequest(xmlURL) {
  var xmlReq;
  if (window.XMLHttpRequest) {
    xmlReq=new XMLHttpRequest();
  } 
  else if(window.ActiveXObject) {
    xmlReq=new ActiveXObject("Microsoft.XMLHTTP");
  } 
  xmlReq.open("GET", xmlURL, false);
  xmlReq.send(null);
  return xmlReq;
}

