//----------------------------------------------------------------------------------------------------------------------
//                                              Validate Routines
//
//  These routines are used to validate a string to see if it a correct representation of something (ie, Number, Integer,
//  ASN1Id, Hexidecimal, etc).  String length can also be validated.  Null or empty strings are considered invalid.  All 
//  routines return true or false.
//
//  Only the validateLength() routine generates alert messages on error.  It is the user's responsibility to generate 
//  error messages when an error in validation is detected (ie, false is returned) for the remaining routines.
//----------------------------------------------------------------------------------------------------------------------


//-------------------------------------------------------------------
// validateNumber - determines if numStr is a valid number.  Allows
// numStr to be an empty string.  If range is specified, also makes 
// sure it is within that range.
// params:
//    numStr - string representation of an interger
//    low -    opt.  Lower end of the range 
//    high -   opt.  Upper end of the range
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateNumber(numStr, low, high)
{
   if (numStr==null || numStr=="")
   {
      return false;
   }
   
   var val = Number(numStr);  //convert string into a number (or NAN)
   var top = ((typeof high=="number") ? high : Number.MAX_VALUE);
   var bottom = ((typeof low=="number") ? low : Number.MIN_VALUE);
   if (isNaN(val) || val>top || val<bottom)
   {
      return false;
   }
   return true;
}

//-------------------------------------------------------------------
// validateInteger - determines if intStr is a valid integer.  Allows
// intStr to be an empty string.  If range is specified, also makes 
// sure it is within that range.
// params:
//    intStr - string representation of an interger
//    low -    opt.  Lower end of the range 
//    high -   opt.  Upper end of the range
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateInteger(intStr, low, high)
{
   if (!validateNumber(intStr, low, high))
   {
      return false;
   }
   
   //it is a valid number in the proper range, but is it an integer?
   var valid = "0123456789 ";
   for (var i=0; i<intStr.length; i++)
   {
      if (valid.indexOf(intStr.charAt(i)) == -1)
      {
         return false;
      }
   }
   return true;
}

//-------------------------------------------------------------------
// validateHex - determines if hexStr is a valid hex string.  
// Optional leading # is allowed.
// params:
//    hexStr - string representation of a hexideciman number
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateHex(hexStr)
{
   if (hexStr==null || hexStr=="" || hexStr=="#")
   {
      return false;  //not a valid hex string
   }
   
   var valid = "0123456789abcdefABCDEF";
   for (var i=((hexStr.charAt(0)=="#")?1:0); i<hexStr.length; i++)
   {
      if (valid.indexOf(hexStr.charAt(i)) == -1)
      {
         return false;
      }
   }
   return true;
}


//-------------------------------------------------------------------
// validateASN1ID - determines if idStr is a valid ASN1ID.
// params:
//    idStr - string representation of an interger
// return:  true if valid, else false with alert message
//-------------------------------------------------------------------
function validateASN1Id(idStr)
{
   if (idStr==null || idStr=="")
   {
      return false;
   }
   
   var valid = "0123456789."
   for (var i=0; i<val.length; i++)
   {
      if (valid.indexOf(idStr.charAt(i)) == -1)
      {
         return false;
      }
   }
   return true;
}

//-------------------------------------------------------------------
// validateLength - determines if txtStr has a valid length.
// params:
//    txtStr - text string
// return:  true if valid, else false with alert message
//-------------------------------------------------------------------
function validateLength(val, low, high, errMsg)
{
   if (val=null)
   {
      return false;
   }
   
   // allow textfields to be empty
   if (val=="" || (low==null && high==null))
   {
      return true;   //nothing to validate
   }
   
   var errMsg = getLengthErrMsg(val, low, high);
   return errMsg==null;
}

//private method
function getLengthErrMsg(val, low, high)
{
   var errMsg=null;
   if (low==null)
   {
      low = high;    //only high was supplied
   } 
   
   if (high==null)
   {
      high = low;    //only low was supplied
   }
   
   if (val.length<low || val.length>high)
   {
      if (low==high)
      {
         errMsg = formatMessage(window.rc_invalidExactStringLengthMsg, [low] );
      }
      else
      {
         errMsg = formatMessage(window.rc_invalidStringLengthMsg, [low,high] );
      }
   }
   return errMsg;
}

//----------------------------------------------------------------------------------------------------------------------
//                                         Validate Field Routines
//
//  These routines are used to validate the entry in a specified html form element field to see if the entered information
//  is in the desired format (ie, Number, Integer, ASN1Id, Hexidecimal, etc).  String length can also be validated.  
//  All routines return true or false and display the error message when an error condition is detected.  Standard error
//  messages are displayed if the errMsg field is omitted (or not required).
//
//  USAGE NOTES:  To use these functions, each html field must be assigned an unique ID attribute.  A hidden div can be
//  provided for each field to be validated with the ID name+"Error" which will become visible when an error is detected 
//  and invisible when the error is cleared.  The appropriate validation function must be called from an onBlur error handler 
//  for each field to be validated.  Finally, the isFormDataValid() function must be called when attempt is made to submit 
// the form (ex, user click OK button).  If it returns false, the submit must be programatically cancelled (so the invalid 
// fields can be entered).
//
//  If the bReq flag is set, empty strings (ie, strings of length zero) are considered invalid.  
//----------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------
// validateNumberField - determines if the specified field contains a valid
// string representation of a number.  Allows field to contain an 
// empty string.  If range is specified, also makes sure it is within that range.
// params:
//    field -  html element containing name of html fields to get value of
//    bReq -   opt.  true, an empty string is not considered valid; false, empty string is allowed
//    low -    opt.  Lower end of the range 
//    high -   opt.  Upper end of the range
//    errMsg - opt.  error message to display on invalid value
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateNumberField(field, bReq, low, high, errMsg)
{
   var val = field.value;
   if ((bReq==null || bReq==false) && val=="")
   {
      clearValidationInfo(field);
      return true;   //ok to have an empty string if optional field
   }
   
   var success = validateNumber(val, low, high);
   if (!success)
   {
      if (errMsg==null || errMsg.length==0)
      {
         errMsg = window.rc_invalidNumberMsg;
      }
      errMsg = createErrMsg(errMsg,low,high);
      setValidationInfo(field, bReq, low, high, errMsg);
      return false;
   }
   clearValidationInfo(field);
   return true;
}

//-------------------------------------------------------------------
// validateIntegerField - determines if the specified field contains a valid 
// string representation of an integer.  Allows field to contain an 
// empty string.  If range is specified, also makes sure it is within that range.
// params:
//    field -  html element containing name of html fields to get value of
//    bReq -   opt.  true, an empty string is not considered valid; false, empty string is allowed
//    low -    opt.  Lower end of the range 
//    high -   opt.  Upper end of the range
//    errMsg - opt.  error message to display on invalid value
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateIntegerField(field, bReq, low, high, errMsg)
{
   var val = field.value;
   if ((bReq==null || bReq==false) && val=="")
   {
      clearValidationInfo(field);
      return true;   //ok to have an empty string if optional field
   }
   
   var success = validateInteger(val, low, high);
   if (!success)
   {
      if (errMsg==null || errMsg.length==0)
      {
         errMsg = window.rc_invalidIntegerMsg;
      }
      errMsg = createErrMsg(errMsg,low,high);
      setValidationInfo(field, bReq, low, high, errMsg);
      return false;
   }
   clearValidationInfo(field);
   return true;
}

//-------------------------------------------------------------------
// validateHexField - determines if the specified field contains a valid 
// string representation of a hex number.  Allows field to contain an 
// empty string.  If range is specified, also makes sure it is within that range.
// params:
//    field -  html element containing name of html fields to get value of
//    bReq -   opt.  true, an empty string is not considered valid; false, empty string is allowed
//    errMsg - opt.  error message to display on invalid value
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateHexField(field, bReq, errMsg)
{
   var val = field.value;
   if ((bReq==null || bReq==false) && val=="")
   {
      clearValidationInfo(field);
      return true;   //ok to have an empty string if optional field
   }
      
   var success = validateHex(val);
   if (!success)
   {
      if (errMsg==null || errMsg.length==0)
      {
         errMsg = window.rc_invalidHexNumberMsg;
      }
      setValidationInfo(field, bReq, null, null, errMsg);
      return false;
   }
   clearValidationInfo(field);
   return true;
}

//-------------------------------------------------------------------
// validateASN1IdField - determines if the specified field contains a valid 
// string representation of an ASN1Id.  Allows field to contain an 
// empty string.  If range is specified, also makes sure it is within that range.
// params:
//    field -  html element containing name of html fields to get value of
//    bReq -   opt.  true, an empty string is not considered valid; false, empty string is allowed
//    errMsg - opt.  error message to display on invalid value
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateASN1IdField(field, bReq, errMsg)
{
   var val = field.value;
   if ((bReq==null || bReq==false) && val=="")
   {
      clearValidationInfo(field);
      return true;   //ok to have an empty string if optional field
   }
      
   var success = validateASN1ID(val);
   if (!success)
   {
      if (errMsg==null || errMsg.length==0)
      {
         errMsg = window.rc_invalidASN1IdMsg;
      }
      setValidationInfo(field, bReq, null, null, errMsg);
      return false;
   }
   clearValidationInfo(field);
   return true;
}

//-------------------------------------------------------------------
// validateLengthField - determines if the specified field contains a string 
// string whose length is within specified bounds.  Allows field to contain an 
// empty string.  If range is specified, also makes sure it is within that range.
// params:
//    field -  html element containing name of html fields to get value of
//    bReq -   opt.  true, an empty string is not considered valid; false, empty string is allowed
//    low -    opt.  Lower end of the range 
//    high -   opt.  Upper end of the range
//    errMsg - opt.  error message to display on invalid value
// return:  true if valid, else false
//-------------------------------------------------------------------
function validateLengthField(field, low, high)
{
   var val = field.value;
   var success = validateLengthLength(val, low, high);
   if (!success)
   {
      var errMsg = getLengthErrMsg(val, low, high);
      setValidationInfo(field, null, low, high, errMsg);
      return false;
   }
   clearValidationInfo(field);
   return true;
}

//-------------------------------------------------------------------
// isFormDataValid() - call before submitting a form to determines if any field on the page 
// has an invalid value.  Invalid entries are identified by the various onBlur() validate field calls. 
// return:  true if all entries are valid, false if any field is invalid (and displays error message)
//-------------------------------------------------------------------
function isFormDataValid()
{
   if (!exists(window.validationInfo) && window.validationInfo!=null)
   {
      for (var i in window.validationInfo)
      {
         if (window.validationInfo[i]!=null)
         {
            //show first invalid field
            var vo = window.validationInfo[i];
            var field = document.getElementById(vo.id);
            if (field!=null)
            {
               //first error located on page
               alert(vo.errMsg);
               field.focus();
               field.select();
               return false;
            }
         }
      }
      window.validationInfo = null;    //every entry is null; null out entire array
   }
   return true;
}

//---------------------- validation infastructure ---------------------------------

function ValidationInfo()
{
   var id;
	var req = false;  //assume not required
	var low;
	var high;
	var errMsg;
}

function setValidationInfo(field, bReq, low, high, errMsg)
{
   if (field!=null && field.id!=null && field.id.length>0)
   {
      if (!window.validationInfo)
      {
         window.validationInfo = new Array();
      }
      var vi = new ValidationInfo();
      vi.id = field.id;
      vi.req = bReq;
      vi.low = low;
      vi.high = high;
      vi.errMsg = errMsg;
      window.validationInfo[field.id] = vi;
      var errField = document.getElementById(field.id+"Error");
      if (errField!=null)
      {
         errField.style.display="inline";
         errField.alt=errMsg;
         errField.title=errMsg;
      }
   }
}

function clearValidationInfo(field)
{
   if (field!=null && field.id!=null && field.id.length>0)
   {
      if (window.validationInfo && window.validationInfo[field.id]!=null)
      {
         window.validationInfo[field.id] = null;
      }
      var errField = document.getElementById(field.id+"Error");
      if (errField!=null)
      {
         errField.style.display="none";
         errField.alt="";
         errField.title="";
      }
   }
}

//----------------------------------------------------------------------------------------------------------------------
//                                                Misc Routines
//----------------------------------------------------------------------------------------------------------------------
function convertDecToHex(dec)
{
   dec = Math.abs(dec);
   var hex = "";
   var a = "" + dec;
   a = a.length;
   var h = "0123456789ABCDEF";
   for (n=0; n<a; n++)
   {
      he = h.charAt(dec-Math.floor(dec/16)*16);
      dec = (dec - h.indexOf(he)) / 16;
      hex = he + hex;
   }
   if (hex.charAt(0) == "0")
      hex = hex.substring(1,hex.length);
   return hex;
}

function createErrMsg(errMsg, low, high)
{
   low = ((low==null)?Number.MIN_VALUE:low);
   high = ((high==null)?Number.MAX_VALUE:high);
   return formatMessage(errMsg, [low, high]);
}