// Public Simple OS code -- can be called by the developer's javascript.  Developer must create
// an object which contains the following member variables.  Either the OS.control or OS.callBack
// parameter must be defined.

function doDynamicOS(userContext, OS)
{
   //make sure we have an entry for the required parameters
   if ( (OS.control!=null || OS.callBack!=null) )  //do we have a control or callback to handle results
   {
      //make sure we at least have default values for all parameters
      if (OS.control==null)                     OS.control="";
      if (OS.callBack==null)                    OS.callBack="";
      if (OS.advancedSelection==null)           OS.advancedSelection="";
      if (OS.initialContext==null)              OS.initialContext="";
      if (OS.isOSAllowed==null)                 OS.isOSAllowed="";
      if (OS.mode==null)                        OS.mode="";
      if (OS.multiSelect==null)                 OS.multiSelect="";
      if (OS.nameFilter==null)                  OS.nameFilter="";
      if (OS.resultsPerPage==null)              OS.resultsPerPage="";
      if (OS.searchSubContainers==null)         OS.searchSubContainers="";
      if (OS.searchOnStartup==null)             OS.searchOnStartup="";
      if (OS.showSubClasses==null)              OS.showSubClasses=="";
      if (OS.typeFilter==null)                  OS.typeFilter="";
      if (OS.typeFilterCallBack==null)          OS.typeFilterCallBack="";
      if (OS.windowed==null)                    OS.windowed="";

      //call the private doOS routine
      doOS(userContext,
           OS.control,
           OS.callBack,

           OS.advancedSelection,
           OS.initialContext,
           OS.isOSAllowed,
           OS.mode,
           OS.multiSelect,
           OS.nameFilter,
           OS.resultsPerPage,
           OS.searchSubContainers,
           OS.searchOnStartup,
           OS.showSubClasses,
           OS.typeFilter,
           OS.typeFilterCallBack,
           OS.windowed);
   }
}


// Private Simple OS code -- not intended for eMFrame developer use.
// These apis are not public and are subject to change without notice. -->

function doOS( userContext,         // user session context info
               controlName,         // name of HTML control that will receive results
               callBack,            // routine to process selected results

               advSel,              // opt - false (default) name-search only, true advanced selection criterion
               initialContext,      // opt - initial container to search from ([root] default)
               isOSAllowed,         // opt - routine to determine if OS should run at all
               mode,                // opt - search (default)or browse
               multiSelect,         // opt - false (default) single select, true multi-select
               nameFilter,          // opt - initial name filter (* default)
               resultsPerPage,      // opt - number of objects to display at a time
               searchSubContainers, // opt - true (default) search subcontainers, false find objects in only the specified container
               searchOnStartup,     // opt - false (default) wait for user to click search button,
                                    //       true, search container on startup
               showSubClasses,      // opt - true - base and derived classes found, false (default) - only base class found
               typeFilter,          // opt - type filter (all default)
               typeFilterCallBack,  // opt - routine to return type filter
               windowed)            // opt - true = object selector in separate window; false(default)= object selector in task window
{
   // Check to see if OSFooter has been included
   if (fw_isDebugEnabled && document.getElementById("OSExchangerFrame")==null)
   {
      var msg = "Developer Alert:  No OSFooter detected on this page.\n\n"+
                "You must include the file 'dev\OSFooter_inc.jsp' once after the last </form> tag\n"+
                "on any page that includes an Object Selector button.\n\n"+
                "Sample code snipits:\n"+
                "   jsp conduit:\t<jsp:include page='\<\%= c.getPath(\"dev/OSFooter_inc.jsp\") \%\>' flush=\"true\"/>\n"+
                "   iman tag library:\t<iman:osFooter/>\n"+
                "   xsl (deprecated):\t<xsl:call-template name=\"OSFooter\"/>";
      alert(msg);
   }

   //make sure we have a valid control or callback
   if (controlName==null)           controlName="";
   if (callBack==null)              callBack="";
   if (controlName.length>0 || callBack.length>0)
   {
      var doOS=true;   //assume we will be running the object selector
      if (exists(isOSAllowed))
      {
         //execute specified routine to determine if search should proceed
         doOS=eval(isOSAllowed+"('"+toScript(controlName)+"')");
      }

      if (doOS)
      {
         //retrieve type filter from type filter callback, if a callback is specified
         if (exists(typeFilterCallBack))
         {
            typeFilter=eval(typeFilterCallBack+"('"+toScript(controlName)+"')");
         }

         //call the task's preOS function
         if (exists("preOS")) preOS(controlName);

         //make sure we have valid windowed parameter
         if (windowed==null || windowed.length==0)
         {
            windowed="false";    //default mode
         }
         else
         {
            windowed = windowed.toLowerCase();
         }
         if (windowed=="true")
         {
            //bring up the object selector in a separate window (default mode)
            var urlParms = "&User.context="+userContext+
                           "&OS.Control="+controlName+
                           "&OS.CallBack="+callBack+
                           "&OS.AdvancedSelection="+advSel+
                           "&OS.InitialContext="+urlEncode(initialContext)+
                           "&OS.IsOSAllowed="+isOSAllowed+
                           "&OS.Mode="+mode+
                           "&OS.MultiSelect="+multiSelect+
                           "&OS.NameFilter="+urlEncode(nameFilter)+
                           "&OS.QueryWidth="+window.osQueryColumnWidth+
                           "&OS.ResultsPerPage="+resultsPerPage+
                           "&OS.SearchSubContainers="+searchSubContainers+
                           "&OS.SearchOnStartup="+searchOnStartup+
                           "&OS.ShowSubClasses="+showSubClasses+
                           "&OS.TypeFilter="+urlEncode(typeFilter)+
                           "&OS.TopMargin=10"+
                           "&OS.URLUniqueId="+Math.random();

            var url = 'webacc?taskId=fw.ObjectSelector&merge=fw.OS.ObjectSelector&error=dev.GenErr&SearchToken=SearchTokenInit'+urlParms;
            var winWidth = ((screen.availWidth<window.osWidth)?screen.availWidth:window.osWidth);
            var winHeight = ((screen.availHeight<window.osHeight)?screen.availHeight:window.osHeight);
            var leftPos = (screen.availWidth-winWidth)/2;
            var topPos =  (screen.availHeight-winHeight)/3;
            var winOpts = 'toolbar=no,location=no,directories=no,menubar=no,scrollbars=yes,resizable=yes,left='+leftPos+',top='+topPos+',width='+winWidth+',height='+winHeight;
            
            //clear contents in an open OS window
            try
            {
               var w = window.open( "webacc?taskId=dev.Empty&merge=fw.Empty&clearOpenOS", 'ObjectSelectorWindow', winOpts);
            }
            catch (e)
            {
               //do nothing
            }
            
            //open new OS window
            var w = window.open( url, 'SimpleOSWindow', winOpts);
            if (w != null)
            {
               // make the window really be size winWidth,winHeight (not just the doc area) and give it focus.
               w.resizeTo(winWidth,winHeight);
            }
         }
         else
         {
            //bring up the object selector in the task window
            //set up required object selector variables
            setOSFooterElementValue("OS.Control",controlName);
            setOSFooterElementValue("OS.CallBack",callBack);

            //set up optional object selector variables
            setOSFooterElementValue("OS.AdvancedSelection",false);   //unused
            setOSFooterElementValue("OS.AnchorDocState",saveDocumentStateInfo());
            setOSFooterElementValue("OS.InitialContext",initialContext);
            setOSFooterElementValue("OS.IsOSAllowed",isOSAllowed);
            setOSFooterElementValue("OS.Mode",mode);
            setOSFooterElementValue("OS.MultiSelect",multiSelect);
            setOSFooterElementValue("OS.NameFilter",nameFilter);
            setOSFooterElementValue("OS.ResultsPerPage",resultsPerPage);
            setOSFooterElementValue("OS.SearchSubContainers",searchSubContainers);
            setOSFooterElementValue("OS.SearchOnStartup",searchOnStartup);
            setOSFooterElementValue("OS.ShowSubClasses",showSubClasses);
            setOSFooterElementValue("OS.TypeFilter",typeFilter);
            setOSFooterElementValue("OS.URLUniqueId",Math.random());

            //set up webaccess object selector values
            setOSFooterElementValue("User.context",userContext);
            setOSFooterElementValue("taskId","fw.ObjectSelector");
            setOSFooterElementValue("merge","fw.OS.ObjectSelector");
            setOSFooterElementValue("error","dev.GenErr");

            //submit
            document.OSFooterPostData.submit();
         }
      }//doOS
   }
   else
   {
      alert("doOS: invalid control and callback...\n  control="+control+"\n  callBack="+callBack);
   }
}

function doOS( userContext,         // user session context info
               controlName,         // name of HTML control that will receive results
               callBack,            // routine to process selected results

               advSel,              // opt - false (default) name-search only, true advanced selection criterion
               initialContext,      // opt - initial container to search from ([root] default)
               isOSAllowed,         // opt - routine to determine if OS should run at all
               mode,                // opt - search (default)or browse
               multiSelect,         // opt - false (default) single select, true multi-select
               nameFilter,          // opt - initial name filter (* default)
               resultsPerPage,      // opt - number of objects to display at a time
               searchSubContainers, // opt - true (default) search subcontainers, false find objects in only the specified container
               searchOnStartup,     // opt - false (default) wait for user to click search button,
                                    //       true, search container on startup
               showSubClasses,      // opt - true - base and derived classes found, false (default) - only base class found
               typeFilter,          // opt - type filter (all default)
               typeFilterCallBack,  // opt - routine to return type filter
               windowed,
               authName)            // opt - true = object selector in separate window; false(default)= object selector in task window
{
   // Check to see if OSFooter has been included
   if (fw_isDebugEnabled && document.getElementById("OSExchangerFrame")==null)
   {
      var msg = "Developer Alert:  No OSFooter detected on this page.\n\n"+
                "You must include the file 'dev\OSFooter_inc.jsp' once after the last </form> tag\n"+
                "on any page that includes an Object Selector button.\n\n"+
                "Sample code snipits:\n"+
                "   jsp conduit:\t<jsp:include page='\<\%= c.getPath(\"dev/OSFooter_inc.jsp\") \%\>' flush=\"true\"/>\n"+
                "   iman tag library:\t<iman:osFooter/>\n"+
                "   xsl (deprecated):\t<xsl:call-template name=\"OSFooter\"/>";
      alert(msg);
   }

   //make sure we have a valid control or callback
   if (controlName==null)           controlName="";
   if (callBack==null)              callBack="";
   if (controlName.length>0 || callBack.length>0)
   {
      var doOS=true;   //assume we will be running the object selector
      if (exists(isOSAllowed))
      {
         //execute specified routine to determine if search should proceed
         doOS=eval(isOSAllowed+"('"+toScript(controlName)+"')");
      }

      if (doOS)
      {
         //retrieve type filter from type filter callback, if a callback is specified
         if (exists(typeFilterCallBack))
         {
            typeFilter=eval(typeFilterCallBack+"('"+toScript(controlName)+"')");
         }

         //call the task's preOS function
         if (exists("preOS")) preOS(controlName);

         //make sure we have valid windowed parameter
         if (windowed==null || windowed.length==0)
         {
            windowed="false";    //default mode
         }
         else
         {
            windowed = windowed.toLowerCase();
         }
         if (windowed=="true")
         {
            //bring up the object selector in a separate window (default mode)
            var urlParms = "&User.context="+userContext+
                           "&OS.Control="+controlName+
                           "&OS.CallBack="+callBack+
                           "&OS.AdvancedSelection="+advSel+
                           "&OS.InitialContext="+urlEncode(initialContext)+
                           "&OS.IsOSAllowed="+isOSAllowed+
                           "&OS.Mode="+mode+
                           "&OS.MultiSelect="+multiSelect+
                           "&OS.NameFilter="+urlEncode(nameFilter)+
                           "&OS.QueryWidth="+window.osQueryColumnWidth+
                           "&OS.ResultsPerPage="+resultsPerPage+
                           "&OS.SearchSubContainers="+searchSubContainers+
                           "&OS.SearchOnStartup="+searchOnStartup+
                           "&OS.ShowSubClasses="+showSubClasses+
                           "&OS.TypeFilter="+urlEncode(typeFilter)+
                           "&OS.TopMargin=10"+
                           "&OS.URLUniqueId="+Math.random()
                           "&OS.AuthName="+authName;

            var url = 'webacc?taskId=fw.ObjectSelector&merge=fw.OS.ObjectSelector&error=dev.GenErr&SearchToken=SearchTokenInit'+urlParms;
            var winWidth = ((screen.availWidth<window.osWidth)?screen.availWidth:window.osWidth);
            var winHeight = ((screen.availHeight<window.osHeight)?screen.availHeight:window.osHeight);
            var leftPos = (screen.availWidth-winWidth)/2;
            var topPos =  (screen.availHeight-winHeight)/3;
            var winOpts = 'toolbar=no,location=no,directories=no,menubar=no,scrollbars=yes,resizable=yes,left='+leftPos+',top='+topPos+',width='+winWidth+',height='+winHeight;
            //alert("OSSimpleScripts.js URL: "+url);
             
            //clear contents in an open OS window
            try
            {
               var w = window.open( "webacc?taskId=dev.Empty&merge=fw.Empty&clearOpenOS", 'ObjectSelectorWindow', winOpts);
            }
            catch (e)
            {
               //do nothing
            }
            
            //open new OS window
            var w = window.open( url, 'SimpleOSWindow', winOpts);
            if (w != null)
            {
               // make the window really be size winWidth,winHeight (not just the doc area) and give it focus.
               w.resizeTo(winWidth,winHeight);
            }
         }
         else
         {
            //bring up the object selector in the task window
            //set up required object selector variables
            setOSFooterElementValue("OS.Control",controlName);
            setOSFooterElementValue("OS.CallBack",callBack);

            //set up optional object selector variables
            setOSFooterElementValue("OS.AdvancedSelection",false);   //unused
            setOSFooterElementValue("OS.AnchorDocState",saveDocumentStateInfo());
            setOSFooterElementValue("OS.InitialContext",initialContext);
            setOSFooterElementValue("OS.IsOSAllowed",isOSAllowed);
            setOSFooterElementValue("OS.Mode",mode);
            setOSFooterElementValue("OS.MultiSelect",multiSelect);
            setOSFooterElementValue("OS.NameFilter",nameFilter);
            setOSFooterElementValue("OS.ResultsPerPage",resultsPerPage);
            setOSFooterElementValue("OS.SearchSubContainers",searchSubContainers);
            setOSFooterElementValue("OS.SearchOnStartup",searchOnStartup);
            setOSFooterElementValue("OS.ShowSubClasses",showSubClasses);
            setOSFooterElementValue("OS.TypeFilter",typeFilter);
            setOSFooterElementValue("OS.URLUniqueId",Math.random());

            //set up webaccess object selector values
            setOSFooterElementValue("User.context",userContext);
            setOSFooterElementValue("taskId","fw.ObjectSelector");
            setOSFooterElementValue("merge","fw.OS.ObjectSelector");
            setOSFooterElementValue("error","dev.GenErr");

            //submit
            document.OSFooterPostData.submit();
         }
      }//doOS
   }
   else
   {
      alert("doOS: invalid control and callback...\n  control="+control+"\n  callBack="+callBack);
   }
}


//set the named element in footer post data form to the specified value
function setOSFooterElementValue(elementName, elementValue)
{
   if (elementName!=null && elementName.length>0)
   {
      for (var j=0; j<document.OSFooterPostData.elements.length; j++)
      {
         if (document.OSFooterPostData.elements[j].name == elementName)
         {
            //alert("setForm0ElementValue: "+elementName+" = "+elementValue);
            document.OSFooterPostData.elements[j].value = elementValue;
            return;
         }
      }
   }
   //alert("setOSFooterElementValue: couldn't find "+elementName);
}

function saveDocumentStateInfo()
{
   var cnt = 0;
   var strControls = "";
   var strControlName = "";

   // for all forms
   for(var i=0; i < document.forms.length; i++)
   {
      //for all elements on each form
      for(var j=0; j < document.forms[i].elements.length; j++)
      {
         //get the name and type of each element
         element = document.forms[i].elements[j];
         if (element != null)
         {
            strControlName = element.name;

            //make sure we don't save the search variables or passwords
            if ( (element.type != null && element.type.toLowerCase() != "password") &&
                 (strControlName != null) &&
                 (strControlName != "OS.Control") &&
                 (strControlName != "OS.CallBack") &&
                 (strControlName != "OS.AdvancedSelection") &&
                 (strControlName != "OS.AnchorDocState") &&
                 (strControlName != "OS.InitialContext") &&
                 (strControlName != "OS.IsOSAllowed") &&
                 (strControlName != "OS.Mode") &&
                 (strControlName != "OS.MultiSelect") &&
                 (strControlName != "OS.NameFilter") &&
                 (strControlName != "OS.ResultsPerPage") &&
                 (strControlName != "OS.SearchSubContainers") &&
                 (strControlName != "OS.SearchOnStartup") &&
                 (strControlName != "OS.ShowSubClasses") &&
                 (strControlName != "OS.TypeFilter") &&
                 (strControlName != "OS.TopMargin") &&
                 (strControlName != "OS.Results") &&
                 (strControlName != "OS.URLUniqueId") )
            {
               //remember this element and its single value
               //REMIND:  need to fix for multiple values
               if (cnt>0)
               {
                  strControls += "$";  //add the separator
               }

               //save the name and state information for this control
               strControls += getHTMLElementStateInfo(element,i);
               cnt++;
            }
         }
      }
   }
   return (strControls);
}

//given a '$' separated string of element state information parameters,
//find each named HTML element and restore its associated value
function restoreDocStateInfo(docState)
{
   if (docState != null && docState.length != 0)
   {
      var elementStates = new Array();

      //parse the element state info from the string
      elementStates = docState.split("$");

      //restore state info for each element
      for (var i=0; i<elementStates.length; i++)
      {
         setHTMLElementStateInfo(elementStates[i]);
      }
   }
}

function getHTMLElementStateInfo(element, formIndex)
{
   var ret = "";
   if (element==null ||
       formIndex<0 || formIndex>document.forms.length)
   {
      return ret;
   }

   //we have a valid HTML element
   var controlName = element.name;
   if (controlName == null || controlName.length<1)
   {
      return ret;
   }

   //we have a valid control name
   var ctrlRef = formIndex+":"+controlName;
   ret = urlEncode(ctrlRef) + "=";
   var controlType = element.type;
   if (controlType == null || controlType.length<1)
   {
      return ret;
   }

   //we have an HTML type string
   controlType = controlType.toLowerCase();
   if (controlType == "checkbox")
   {
      //checkbox element
      //syntax: <elementName>=<checkedState>=<value>)
      ret += urlEncode(element.checked) + "=";
      ret += urlEncode(element.value);
   }
   else if (controlType == "radio")
   {
      //radio element
      //syntax: <elementName>=<formIndex>=<buttonIndx>=<checkedState>=<value>)
      var btnIndex = getButtonIndex(formIndex,element);
      if (btnIndex != -1)
      {
         ret += formIndex + "=";
         ret += btnIndex + "=";
         ret += urlEncode(element.checked) + "=";
         ret += urlEncode(element.value);
      }
   }
   else if (controlType == "select-one" ||
            controlType == "select-multiple")
   {
      //select element
      //syntax: <selectName>=[<option text>=<option value>=<selected flag>]
      for (i=0; i<element.options.length; i++)
      {
         if (i>0)
         {
            ret += "=";
         }
         ret += urlEncode(element.options[i].text) + "=";
         ret += urlEncode(element.options[i].value) + "=";
         ret += urlEncode(element.options[i].selected);
      }
   }
   else if (controlType == "file")
   {
      // file value attribute is read-only; it can't be saved
      ret = "";
   }
   else
   {
      //all remaining html elements
      //syntax: <elementName>=<value>)
      ret += urlEncode(element.value);
   }
   return ret;
}

function setHTMLElementStateInfo(stateInfo)
{
   if (stateInfo == null || stateInfo.length<1)
   {
      return;  //no state info string
   }

   var infoArray = stateInfo.split("=");
   if (infoArray == null)
   {
      return;  //no state info values
   }

   // parse state information
   var len = infoArray.length;
   switch (len)
   {
      case 0:
         // nothing do do
         break;

      case 1:
         // clear out this control's value
         setFormElementValue(urlDecode(infoArray[0]),"");
         break;

      case 2:
         //we have a single name=value pair
         setFormElementValue(urlDecode(infoArray[0]), urlDecode(infoArray[1]));
         break;

      default:
      {
         // we must have a complex HTML element
         var ctrlRef = urlDecode(infoArray[0]);
         var element = findFormElement(ctrlRef);
         if (element != null)
         {
            var controlName = element.name;
            var controlType = element.type;
            if (controlType == "checkbox")
            {
               //<checkbox> element
               //syntax: <elementName>=<checkedState>=<value>)
               element.checked = (urlDecode(infoArray[1])=="true");
               element.value = urlDecode(infoArray[2]);
            }
            else if (controlType == "radio")
            {
               //<radio> element
               //syntax: <elementName>=<formIndex>=<buttonIndx>=<checkedState>=<value>)
               var formIndex = urlDecode(infoArray[1]);
               var btnIndex = urlDecode(infoArray[2]);
               var radioElement = eval('document.forms['+formIndex+'].elements["'+controlName+'"]['+btnIndex+']');
               if (urlDecode(infoArray[3])=="true")
               {
                  radioElement.checked = true;
               }
               radioElement.value = urlDecode(infoArray[4]);
            }
            else if (controlType == "select-one" ||
                     controlType == "select-multiple")
            {
               //<select> element
               //syntax: <selectName>=[<option text>=<option value>=<selected flag>]
               //REMIND:  need to do this differently on PDA since can't remove/resize options!

               // clear options array
               element.options.length=0;

               // add options back into list
               var cnt=0;
               for (i=1; i<len; i++)
               {
                  element.options[cnt]=new Option(urlDecode(infoArray[i]),              // text
                                                  urlDecode(infoArray[i+1]));           // value
                  element.options[cnt].defaultSelected = false;
                  element.options[cnt].selected = ((urlDecode(infoArray[i+2])=="true"));

                  i+=2;
                  cnt++;
               }
            }
            else
            {
               //unknown type, assume name=value
               setFormElementValue(ctrlRef,urlDecode(infoArray[1]));
            }
         }
      }
   }
}

//get the group index of a radio button element
function getButtonIndex(formIndex, buttonElement)
{
   var buttonName = buttonElement.name;
   var ret = -1;
   groupLen = eval("document.forms["+formIndex+"].elements['"+buttonName+"'].length");
   for (i=0; i<groupLen; i++)
   {
      if ((eval('document.forms['+formIndex+'].elements["'+buttonName+'"]['+i+']')) == buttonElement)
      {
         ret=i;
         break;
      }
   }
   return ret;
}

//search for the specified form#:element and return it
function findFormElement(element)
{
   if (element!=null && element.length>0)
   {
      //get form # and element name
      var f = 0;
      var name = element;

      var idx = element.indexOf(":");
      if (idx>0 && idx+1<element.length)
      {
         f = parseInt(element);
         name = element.substr(idx+1);
      }
      for (var i=0; i<document.forms[f].elements.length; i++)
      {
         if (document.forms[f].elements[i].name == name)
         {
            return document.forms[f].elements[i];
         }
      }
   }
   return null;
}

//set the named form#:element to a specified value
function setFormElementValue(element, value)
{
   if (element!=null && element.length>0)
   {
      //get form # and element name
      var f = 0;
      var name = element;

      var idx = element.indexOf(":");
      if (idx>0 && idx+1<element.length)
      {
         f = parseInt(element);
         name = element.substr(idx+1);
      }
      if (name.length>0 && document.forms[f]!=null)
      {
         for (var i=0; i<document.forms[f].elements.length; i++)
         {
            if (document.forms[f].elements[i].name == name)
            {
               document.forms[f].elements[i].value = value;
               return;
            }
         }
      }
      //alert("setFormElementvalue: couldn't find "+element);
   }
}

//search all forms for the specified named element.
//the first one located is set to the specified value
function setElementValue(elementName, elementValue)
{
   if (elementName!=null && elementName.length>0)
   {
      for (var i=0; i<document.forms.length; i++)
      {
         for (var j=0; j<document.forms[i].elements.length; j++)
         {
            if (document.forms[i].elements[j].name == elementName)
            {
               //alert("setElementValue: "+elementName+" = "+elementValue);
               document.forms[i].elements[j].value = elementValue;
               return;
            }
         }
      }
   }
   //alert("setElementvalue: couldn't find "+elementName);
}