/**
 * deepmerge. Merges the passed Hash into the current Hash.
 *   Unlike the one defined in core_WebDDM, this one does deep cloning into the first hash
 *    Also, it isn't part of the "hash" package, so you can use it on normal objects
 *
 * @params hash1,hash2 => hashes to merge.  Preference is given to the elements from the left hash.  
 *  (i.e. they won't be overwritten by stuff from the right)
 * @return VOID
 */
function deepmerge(hash1,hash2)
{ for (var tmp_key in hash2) 
  { //If there isn't anything in the object at all, copy it directly over.
    if (typeof(hash1[tmp_key]) == 'undefined') 
    { hash1[tmp_key] = hash2[tmp_key] }
    //If both of the elements are arrays, then concatenate them rather than deep merging.
    else if
    (  typeof(hash1[tmp_key]) == 'object' //Strings have the "concat" function, but they're not objects.  Checking for both things.
    && typeof(hash2[tmp_key]) == 'object' 
    && typeof(hash1[tmp_key].concat)=='function'
    && typeof(hash2[tmp_key].concat)=='function'
    )
     { hash1[tmp_key]= hash1[tmp_key].concat(hash2[tmp_key]) }
       //Otherwise, recurr to deep clone if possible.
    else if
    (  typeof(hash1[tmp_key]) == 'object' 
    && typeof(hash2[tmp_key]) == 'object'
    )
     { hash1[tmp_key] = deepmerge(hash1[tmp_key],hash2[tmp_key]) }
  }
; return hash1
}; // End deepmerge

/**
  * Converts a list of where some of the elements may be singleton strings into an array of hashes.
  *   Implemented as a separate function because its not always needed.
  **/
function WebDDM_contentonly(menuData)
{
// Since we now have the ability to have singleton list elements, 
// we should allow for content only items to be just a string that represents the content.
  if(typeof(menuData)=="string")
    return {'content':menuData} 
; else if(typeof(menuData.items)!="undefined")
    { for(var i=0; i<menuData.items.length; i++)
        menuData.items[i] = WebDDM_contentonly(menuData.items[i]) 
    }
; return menuData
}


/*  This function isn't really needed at the moment.  It might be that we want to do something special at the start.
 */
function WebDDM_depthinherit(menuData, depthData)
{ return WebDDM_depthrecurr(menuData, depthData,0) }

/*
 * I don't like the menu structure syntax.   
 *   So...I'm using a different structure for my functions and then converting over.
 *      Instead of using "items" as an object, I'm making it an array (and also creating a "item_properties" object).
 *      This way we can combine two different menus into one if we want.
 *      This is a conversion function that switches to the hash version for the WebDDM stuff.
 *   Input:  menuData where "items" is an array, and "item_properties" is an object.
 *   Output:  menuData where "items" is an object, and "item_properties" doesn't exist.
 */
function WebDDM_convert_to_webddm(menuData)
{ if(typeof(menuData.items)!="undefined")
  { var newdata = new Object()
  ; for(var i=0; i<menuData.items.length; i++)
    { newdata[i+1] = menuData.items[i]; 
      newdata[i+1] = WebDDM_convert_to_webddm(newdata[i+1]) 
    }
  ; for(var elem in menuData.item_properties)
      newdata[elem]=menuData.item_properties[elem]
  ; menuData.items = newdata;
  }
; delete(menuData.item_properties)
; return menuData
}

/**
  * Allows you to add characteristics based on depth.
  * Does a union, but preference is given to the existing data.
  * 
  **/
function WebDDM_depthrecurr(menuData,depthData,depth)
{ //Add all of the characteristics at the given menu depth to the menu.
  if(typeof(depthData[depth])!="undefined")
        menuData=deepmerge(menuData,depthData[depth]);
  //Iterate over the items hash, and call depthrecurr for each element.
; if(typeof(menuData.items)!="undefined")
  { //Set each item element to have the same result.  This is based on the assumption that items is actually an array.
  ; for(var itemIndex=0; itemIndex<menuData.items.length; itemIndex++){
      var depth_recurr = WebDDM_depthrecurr(menuData.items[itemIndex],depthData,depth+1);
      if(itemIndex!=0)
        menuData.items[itemIndex] = depth_recurr;
      else{//Throw out the offset for the first item in each list.
        var tmp_depth_recurr=depth_recurr;
        tmp_depth_recurr['offsetTop']=0;
        tmp_depth_recurr['offsetLeft']=0;
        menuData.items[itemIndex] = tmp_depth_recurr;
        }
      }
  }
; return menuData
}

