/**
 ******************************************************************************
 *
 * Confidential Property of Documentum, Inc.
 * (c) Copyright Documentum, Inc. 2001.
 * All Rights reserved.
 * May not be used without prior written agreement
 * signed by a Documentum corporate officer.
 *
 ******************************************************************************
 *
 * Project        WDK Forms
 * File           componentnavigation.js
 * Description    WDK Components Navigation Mechanism - requires locate.js, events.js
 *                                                   and formnavigation.js
 * Created on     21 May 2001
 * Tab width      3
 *
 ******************************************************************************
 *
 * PVCS Maintained Data
 *
 * Revision       $Revision: 18$ 
 * Modified on    $Date: 5/3/2005 12:34:30 PM$
 *
 * Log at EOF
 * 
 ******************************************************************************
 */

/**
 * Post a server component page event to a given URL.
 * @param strFormId    The target form for the event.
 * @param strUrl       The url to jump to.
 * @param strTarget    The target frame (Optional - default is current frame)
 * If target frame does not exist then a new window will pop up.
 * @param  strEventArgName  event argument name (Optional)
 * @param  strEventArgValue  event argument value (Optional)
 *
 * Note: Multiple argument names and values may be specified.
 * Note: To specify a start page post an argument called '__dmfPage'.
 */
function postComponentPageEvent(strFormId, strComponent, strTarget, strEventArgName, strEventArgValue)
{
   var arrArgs = getArgs("postComponentPageEvent", 3);
   postComponentNavigationEvent(strFormId, strComponent, "onComponentPage", strTarget, arrArgs);
}

/**
 * Post a server component jump event to a given URL.
 * @param strFormId    The target form for the event.
 * @param strUrl       The url to jump to.
 * @param strTarget    The target frame (Optional - default is current frame)
 * If target frame does not exist then a new window will pop up.
 * @param  strEventArgName  event argument name (Optional)
 * @param  strEventArgValue  event argument value (Optional)
 *
 * Note: Multiple argument names and values may be specified.
 * Note: To specify a start page post an argument called '__dmfPage'.
 */
function postComponentJumpEvent(strFormId, strComponent, strTarget, strEventArgName, strEventArgValue)
{
   var arrArgs = getArgs("postComponentJumpEvent", 3);
   postComponentNavigationEvent(strFormId, strComponent, "onComponentJump", strTarget, arrArgs);
}

/**
 * Post a server component nest event to a given URL.
 * @param strFormId    The target form for the event.
 * @param strUrl       The url to jump to.
 * @param strTarget    The target frame (Optional - default is current frame)
 * If target frame does not exist then a new window will pop up.
 * @param  strEventArgName  event argument name (Optional)
 * @param  strEventArgValue  event argument value (Optional)
 *
 * Note: Multiple argument names and values may be specified.
 * Note: To specify a start page post an argument called '__dmfPage'.
 */
function postComponentNestEvent(strFormId, strComponent, strTarget, strEventArgName, strEventArgValue)
{
   if ((strEventArgName != null) && (strEventArgName != "") && (typeof strEventArgName != "undefined"))
   {
      var arrArgs = getArgs("postComponentNestEvent", 3);
      postComponentNavigationEvent(strFormId, strComponent, "onComponentNested", strTarget, arrArgs);
   }
   else
   {
      var emptyArray = new Array();
      postComponentNavigationEvent(strFormId, strComponent, "onComponentNested", strTarget, emptyArray);
   }
}

/**
 * Post a server event to a given component.
 * @param strFormId    The target form for the event.
 * @param strComponent The component to jump to.
 * @param strEvent     The event to fire.
 * @param strTarget    The target frame (Optional - default is current frame)
 * If target frame does not exist then a new window will pop up.
 * @param  arrArgs  An array of arguments in format as generated by
 *                  getArgs() (Zero length if no args).
 *
 * Note: Multiple argument names and values may be specified.
 * Note: To specify a start page post an argument called '__dmfPage'.
 * Note: If the signature for this method is changed, _postComponentNavigationEventClosure needs to be updated also.
 */
function postComponentNavigationEvent(strFormId, strComponent, strEvent, strTarget, arrArgs)
{
   var strCall = "";

   var strFramePath = getAbsoluteFramePath(strTarget);
   if (strFramePath != null)
   {
      // Frame exists.

      // Walk down to leaf and see if it is a form but first check frame's state,
      // otherwise eval for strCall may not work correctly on Safari [ ends up pointing to parent page ]
      if ( isValidWindow(strFramePath) == true )
      {
         strFramePath = walkDownFrameSet(strFramePath);
         var targetFrame = eval(strFramePath);

         if ( isDispatchableWindow(targetFrame) )
         {
            // Target frame is a WDK form
            strCall = strFramePath + "." + generateSafeCallString(strFormId, arrArgs);
         }
         else
         {
            // Target frame is not a WDK form. Redirect via URL (specify start page if provided)
            var strComponentUrl = generateComponentUrl(getVirtualDir(), strComponent, arrArgs);
            strComponentUrl = addBrowserIdToURL(strComponentUrl);

            strCall = strFramePath + ".location.href = \"" + strComponentUrl + "\"";
         }
      }
      else
      {
         // Get Inner Reference to postComponentNavigationEvent function, with arguments.
         if (Trace_COMPONENTNAVIGATION) componentnavigation_trace("Delaying postComponentNavigationEvent for " + strTarget + " by 100ms");

         var delayed = _postComponentNavigationEventClosure(strFormId, strComponent, strEvent, strTarget, arrArgs);
         return setTimeout(delayed, 100);
      }
   }
   else
   {
      // Frame doesn't exist or target is current page
      if ((strTarget == null) || (typeof strTarget == "undefined"))
      {
         strCall = generateSafeCallString(strFormId, arrArgs);
      }
      else
      {
         // Open new window (with start page if specified)
         var strVirtualRoot = getVirtualDir();
         if(typeof g_virtualRoot != "undefined")
         {
            strVirtualRoot =  g_virtualRoot.substring(1);
         }

         strCall = "window.open(\"" + generateComponentUrl(strVirtualRoot, strComponent, arrArgs) + "\", strTarget)";
      }
   }

   if (Trace_COMPONENTNAVIGATION)
   {
      componentnavigation_trace("About to Eval Component Navigation Call : " + strCall);
      componentnavigation_trace(" - strFormId = " + strFormId);
      componentnavigation_trace(" - strComponent = " + strComponent);
      componentnavigation_trace(" - strEvent = " + strEvent);
      componentnavigation_trace(" - strTarget = " + strTarget);
   }

   eval(strCall);
}

/**
 * Private. Not for public use. Has dependancy on postComponentNavigationEvent signature.
 *
 * Wrapper (Closure) for postComponentNavigationEvent, to be used when postComponentNavigationEvent needs to delay
 * itself, using setTimeout/setInterval. Maintains arguments across the delay, without the need to globalize arguments
 * or covert them to/from strings. See {@link postComponentNavigationEvent}
 */
function _postComponentNavigationEventClosure(strFormId, strComponent, strEvent, strTarget, arrArgs)
{
   return function()
   {
      window.postComponentNavigationEvent(strFormId, strComponent, strEvent, strTarget, arrArgs);
   };
}

///////////////////////////////////////////////////////////////
// Helpers
///////////////////////////////////////////////////////////////

/**
 * Generate the Component Dispatcher URL
 *
 * @param strVirtualRoot - the app server context path
 * @param strComponent - the app server context path
 * @param arrArgs Array of arguments generated by getArgs().
 */
function generateComponentUrl(strVirtualRoot, strComponent, arrArgs)
{
   var strComponentUrl = "/" + strVirtualRoot + "/component/" + strComponent;

   var strPage = retrievePage(arrArgs);
   if (strPage != null)
   {
      strComponentUrl += "/" + strPage;
      arrArgs = removePageFromArray(arrArgs);
   }
   if (arrArgs.length > 0)
   {
      strComponentUrl += "?" + convertArgsToUrlArgString(arrArgs);
   }

   return strComponentUrl;
}

/**
 * Generate the safeCall method call string
 *
 * @param strFormId form which needs to be submitted for safeCall
 * @param arrArgs Array of arguments generated by getArgs().
 */
function generateSafeCallString(strFormId, arrArgs)
{
   var strSafeCall = "";
   if (strFormId)
   {
      strSafeCall = "safeCall('postServerEvent', '" + strFormId + "', null, null, strEvent, '__dmfTargetComponent', strComponent";
   }
   else
   {
      // strFormId == null, strFormId == "", typeof strFormId == "undefined", strFormId == 0, strFormId == false all fall here
      strSafeCall = "safeCall('postServerEvent', null, null, null, strEvent, '__dmfTargetComponent', strComponent";
   }

   if (arrArgs.length > 0)
   {
      strSafeCall += ", " + convertArgsToFunctionString(arrArgs);
   }
   strSafeCall += ")";

   return strSafeCall;
}

/**
 * Retrieve the specified page from the array of arguments (null if it
 * doesn't exist).
 * @param arrArgs Array of arguments generated by getArgs().
 */
function retrievePage(arrArgs)
{
   var strResult = null;
   if (arrArgs.length > 0)
   {
      for (var iArg = 0; iArg < arrArgs.length; iArg+=2)
      {
         if (arrArgs[iArg] == "__dmfPage")
         {
            strResult = arrArgs[iArg + 1];
            break;
         }
      }
   }
   return strResult;
}

/**
 * Remove the specified page from the array of arguments if it exists
 * @param arrArgs Array of arguments generated by getArgs().
 * @return Array  Processed array of arguments.
 */
function removePageFromArray(arrArgs)
{
   var arrResult = new Array();
   var nArrOffset = 0;
   if (arrArgs.length > 0)
   {
      for (var iArg = 0; iArg < arrArgs.length; iArg+=2)
      {
         if (arrArgs[iArg] != "__dmfPage")
         {
            //Add event name and event value to new array.
            arrResult[nArrOffset] = arrArgs[iArg];
            arrResult[nArrOffset + 1] = arrArgs[iArg + 1];
         }
      }
   }
   return arrResult;
}

/**
* Trace Client Events
*
* @param  strMsg  the trace message
*/
function componentnavigation_trace(strMsg)
{
   Trace_println("componentnavigation.js: " + strMsg);
}

