
PageValidator.prototype.IsValidForm = function( formId, formBlock, Validator, IncludeRequired )
{
   //try
   //{

        //check parameters
        if( !formId ) throw Error("Form ID argument is required.");
        //validate all blocks by default
        if( !formBlock ) formBlock = "all";
        //if page validator is off
        if( !this.Validate ) return true;
        //if form not configured or form validation is off
        if( !this.Forms[formId] || !this.Forms[formId].Validate ) return true;

       var IsValid = true;
       var oForm = this.Forms[formId];
       var oFormLength = oForm.elements.length;

       for(var i=oFormLength-1; i>=0; i-- )
       {
           //get current form element
          var oSrcElement = oForm.elements[i];

          //get element's applied logic
          var sPersonality = oSrcElement.getAttribute('ismPersonality');

          //find out element's block
          var sFormBlock = oSrcElement.getAttribute('ieblock');

            //validate correct block only
          if( formBlock != "all" && sFormBlock != formBlock ) continue;

            //get markup element for this element (may not be itself)
          var oMarkUpElement = oSrcElement;

          if( oSrcElement.getAttribute('ai_markup_applies_to') != null )
          {
             var oarrMarkUpElement = formHelper.GetElementsByAttribute('ai_name', oSrcElement.getAttribute('ai_markup_applies_to') );

             for(var z=oarrMarkUpElement.length-1; z >= 0; z--)
             {
                if( formBlock == "all" || oarrMarkUpElement[z].getAttribute('ieblock') == formBlock )
                {
                   oMarkUpElement = oarrMarkUpElement[z];
                   break;
                }
             }
          }

          var sRequired = oSrcElement.getAttribute('ismMandatory');
          var sReadOnly = oSrcElement.getAttribute('ismReadOnly');
          if (sReadOnly == null) sReadOnly = "false";

          if (sPersonality != null && CheckNotVisible(oSrcElement) == false && (sPersonality.toLowerCase() == "qdsingle" || sPersonality.toLowerCase() == "qdmulti"))
          {
             oMarkUpElement = formHelper.AddClassNameHandlers(oMarkUpElement);
             Validator.UnsetFieldError(oMarkUpElement);
          }

          if( (IncludeRequired || AlwaysPerformMandatoryCheck(oSrcElement)) && (sRequired == "true" || sRequired == "1" || sRequired == "Y") &&
          	sReadOnly != "true" && CheckNotVisible(oSrcElement) == false)
          {
             oMarkUpElement = formHelper.AddClassNameHandlers(oMarkUpElement);
             Validator.UnsetFieldError(oMarkUpElement);

             var strElementType = oSrcElement.type.toLowerCase();

             if (strElementType == "checkbox" || strElementType == "radio")
             {
                if( !this.HaveAtLastOneItemChecked(oSrcElement) )
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
             }
             else if (strElementType == "select-one")
             {
                if( !this.HaveSelectedItem(oSrcElement) )
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
             }
             else if (strElementType == "select-multiple")
             {
                if( !this.HaveMultiSelectedItem(oSrcElement) )
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
             }
             else if (strElementType == "file")
             {
                // The file input seems to stop the submit when these conditions aren't met
                // so we duplicate them to provide a message
                if( this.IsBlank(oSrcElement) ||
                    (oSrcElement.value.substring(1,2) != ':' &&
                     oSrcElement.value.substring(0,2) != '\\\\'))
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
             }
             else
             //if( strElementType == 'text' || strElementType == 'textarea' || strElementType == 'password' )
             {
                if( this.IsBlank(oSrcElement) )
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
             }
          }

          // Rules validation
          var sRules = oSrcElement.getAttribute('ai_rules');

          if( sRules != null )
          {
             try
             {
                if( !eval(sRules) )
                {
                   if( oSrcElement.value.length > 0 )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
             }
               catch(ex)
               {
                  throw new Error("Invalid AI_RULES at element " + oSrcElement.id + "<br>" + ex.message);
               }
          }

          if( sPersonality == null ) continue;
          switch (sPersonality.toLowerCase())
          {
             case 'text' :
                if (oSrcElement.value.length > 0)
                {
                   var iMinimun = oSrcElement.getAttribute('ieminlength');
                       var iMaximun = oSrcElement.getAttribute('maxlength');

                   if( iMinimun != null || iMaximun != null )
                   {
                      if( !this.CheckLengthConstraint( oSrcElement, iMinimun, iMaximun ) )
                      {
                      	Validator.SetFieldError(oMarkUpElement);
                        IsValid = false;
                      }
                   }
                }
                break;

             case 'cpf' :
                if (oSrcElement.value.length > 0)
                {
                    var pvm = this.PostValidationMethods["IsValidCPF"];
                   if( pvm && pvm(oSrcElement) == false )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

             case 'cnpj' :
                if (oSrcElement.value.length > 0)
                {
                    var pvm = this.PostValidationMethods["IsValidCNPJ"];
                   if( pvm && pvm(oSrcElement) == false )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

             case 'email' :
                if (oSrcElement.value.length > 0)
                {
                   if( oSrcElement.value.match(RegExTemplates.EMAIL) <= 0 )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

             case 'url' :
                if (oSrcElement.value.length > 0)
                {
                   if( oSrcElement.value.match(RegExTemplates.URL) <= 0 )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

             case 'number' :
                if (oSrcElement.value.length > 0)
                {
                      var dMaxValue = oSrcElement.getAttribute('iemaxvalue');
                       var dMinValue = oSrcElement.getAttribute('ieminvalue');

                    var pvm = this.PostValidationMethods["IsValidNumberRange"];
                   if( pvm && pvm(oSrcElement, dMinValue, dMaxValue) == false )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

             case 'datetime' :
                break;

             case 'date' :
                if (oSrcElement.value.length > 0)
                {
                    var pvm = this.PostValidationMethods["IsValidDate"];
                   if( pvm && pvm(oSrcElement) == false )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

             case 'time' :
                if (oSrcElement.value.length > 0)
                {
                    var pvm = this.PostValidationMethods["IsValidTime"];
                   if( pvm && pvm(oSrcElement) == false )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;

            case 'customdatetime':
                if (oSrcElement.value.length > 0)
                {
                    var pvm = this.PostValidationMethods["IsValidCustomDateTime"];
                   if( pvm && pvm(oSrcElement) == false )
                   {
                      Validator.SetFieldError(oMarkUpElement);
                      IsValid = false;
                   }
                }
                break;


            // LAC - Date Time Picker
            case 'datetimepicker':
                if (DTPValidate(oSrcElement) == false)
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
                break;

           case 'qdsingle':
                if (!this.QDSelectedItem(oSrcElement) && this.HasQDEnteredText(oSrcElement,oForm))
                {
                   Validator.SetFieldWarning(oMarkUpElement);
                   IsValid = false;
                }
                else if (sRequired == "true" && IncludeRequired && !this.QDSelectedItem(oSrcElement) && sReadOnly != "true" && CheckQDNotVisible(oSrcElement) == false)
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
                break;

           case 'qdmulti':
                //# selected items?
                if (!this.QDSelectedItem(oSrcElement) && this.HasQDEnteredText(oSrcElement,oForm))
                {
                   Validator.SetFieldWarning(oMarkUpElement);
                   IsValid = false;
                }
                else if (sRequired == "true" && IncludeRequired && !this.QDSelectedItem(oSrcElement) && sReadOnly != "true" && CheckQDNotVisible(oSrcElement) == false)
                {
                   Validator.SetFieldError(oMarkUpElement);
                   IsValid = false;
                }
                break;

           case 'multitierprofile':
                //# selected items?
                //alert("call multi-tier validation here");
                break;

          }
       }

       var OtherChecksValid = !PerformAdditionalMandatoryChecks(oForm,Validator);
		OtherChecksValid =  !PerformCustomMandatoryChecks(oForm,Validator) || OtherChecksValid;
		//This was run over 2 lines so that custom checks will be run before returning - we want all highlighting to happen in one go

       if (IncludeRequired && OtherChecksValid)
       {
          IsValid = false;
       }

       if( IsValid )
       {
          return true;
       }
       else
       {
          return false;
       }
   //}
   //catch(ex)
   //{
   //    debugHelper.Exception("PageValidator.IsValidForm " + ex.message, document.URL, document.lastModified, document.referrer);
   //    return false;
   //}

}


PageValidator.prototype.QDSelectedItem = function( poElement )
{
   var unselectedValue = poElement.getAttribute('ismUnselectedValue');
   //TODO: check for entered text with no search ref
   if (poElement.value.length == 0)
   {
      return false;
   }
   else if (unselectedValue == null)
   {
      return (poElement.value != "0" && poElement.value != "-1");
   }
   else if (poElement.value == unselectedValue)
   {
      return false;
   }
   return true;

   return false;
}


PageValidator.prototype.HasQDEnteredText = function( poElement, oform )
{
   //Find the QD text field and see if it has entered text
   var SearchFieldName = 'QD_SEARCH_FIELD_' + poElement.id;
   var oSearchField = oform[SearchFieldName];

   if (oSearchField != null)
   {
      var oTextField = oform[oSearchField.value];
      if (oTextField != null)
      {
         return !this.IsBlank(oTextField);
      }
   }

   return false;
}


function AlwaysPerformMandatoryCheck(oSrcElement)
{
  var strElementType = oSrcElement.type.toLowerCase();
  if (strElementType != "select-one") return false;

  var strElementName = oSrcElement.name;
  if (!strElementName || strElementName == "") strElementName = oSrcElement.id;

  if (!strElementName || strElementName == "")
    return false;
  else
  {
    var STEM = "EXTFLDV_";
    var REQ_FORWARD_TO = "CI_REQUEST_FORWARD";
    var CALL_FORWARD_TO = "FORWARD_TO";
    return strElementName != REQ_FORWARD_TO && strElementName != CALL_FORWARD_TO &&
           (strElementName.length < STEM.length ||
            strElementName.substring(0, STEM.length) != STEM);
  }
}


function PerformAdditionalMandatoryChecks(oForm, Validator)
{
   //override on each page to implement mandatory fields from admin settings
   //use the validator fields to set warnings & errors on a field to get the highlighting and default messages to appear.
   return true;
}


function PerformCustomMandatoryChecks(oForm, Validator)
{
   //override on each page to implement custom mandatory fields checks
   //use the validator fields to set warnings & errors on a field to get the highlighting and default messages to appear.
   return true;
}


function CheckNotVisible(elem)
{
   var elemPointer = elem;
   var bReturn = false;

   do
   {
      if (IsFieldHidden(elemPointer))
      {
         bReturn = true;
         break;
      }
      elemPointer = elemPointer.parentNode;

   } while(elemPointer != null);

   return bReturn;
}


// ID starting with "container_" means that the field is hidden because of the access level.
// We want to ignore hidden fields caused by access level and deleted in designer (i.e. in ieDeadZone)
// Fields hidden not because of access level, we will not consider it as hidden, i.e.
// mandatory check still need to take place.
function IsFieldHidden(elemPointer)
{
   return (elemPointer.style != null && elemPointer.style.display == "none") && 
          (StringStartsWith(elemPointer.id, "container_") || elemPointer.id == "ieDeadZone");   
}


function StringStartsWith(sString,sStartWith)
{
   return (sString != null && sString.length >= sStartWith.length && sString.substring(0,sStartWith.length).toUpperCase() == sStartWith.toUpperCase());
}

function CheckQDNotVisible(elem)
{
   var itemname = elem.id;
   var searchfieldname = "QD_SEARCH_FIELD_" + itemname;
   var osearchfld = document.getElementById(searchfieldname);
   if (osearchfld == null) return true;

   var elemPointer = document.getElementById(osearchfld.value);
   var bReturn = false;

   do
   {
      if (elemPointer.style != null && elemPointer.style.display == "none")
      {
         bReturn = true;
         break;
      }
      elemPointer = elemPointer.parentNode;

   } while(elemPointer != null);

   return bReturn;
}
