/* Copyright 2005 - 2007 Spring Layout Development Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * Functions in this file relate to the Spring Layout Validation. It provides the core validation
 * functions.
 *
 * @author Adam Boas
 */

/**
* Class definition for the base validator. Provides basic validation functionality and
* a base for extension for more complex validation.
*/
function validateMandatory(fieldName)
{
   var fieldValue = $F(fieldName);
   if(fieldValue == null || trim(fieldValue) == "")
   {
      return false;
   }
   else
   {
      return true;
   }
}

/**
 * Helper method to trim whitespace
 * @param {Object} string to trim whitespace from
 */
function trim(string)
{
   var trimRegex = /^\s+(.*?)\s+$/;
   return string.replace(trimRegex, "$1");
}

/**
 * Check that field contains only numbers
 * @param {Object} fieldOrId
 * @param {Object} displayAlert
 */
function validateNumber(fieldOrId, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;
   var re = new RegExp(/^\d+$/);
   if(field.value.match(re))
      return true;

   displayOptionalAlert("Field was not a number", displayAlert);
   return false;
}

/**
 * Check that field contains only decimal numbers
 * @param {Object} fieldOrId
 * @param {Object} maxFractionDigits
 * @param {Object} displayAlert
 */
function validateDecimal(fieldOrId, maxFractionDigits, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   // If basic format not satisfied, error.
   if (!field.value.match(new RegExp(/^\d*(\.\d+)?$/)))
   {
      displayOptionalAlert("Field was not a decimal number", displayAlert);
      return false;
   }

   // If optional argument is specified, check number of fraction digits.
   if (maxFractionDigits != null)
   {
	   var digits = field.value.split(".");
	   var hasFraction = (digits.length == 2);

	   if (hasFraction)
	   {
	      if (digits[1].length > maxFractionDigits)
	      {
	         displayOptionalAlert(
	               "Please ensure the value you have entered is to a maximum of " + maxFractionDigits +" decimal places.",
	               displayAlert);
	         return false;
	      }
	   }
   }

   return true;
}

/**
 * Validates basic email format.
 * @param {Object} fieldOrId
 * @param {Object} displayAlert
 */
function validateEmail(fieldOrId, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   var re = new RegExp(/^[\w\.]+@\w+\.\w{2,3}(\.\w{2})?$/);
   if(field.value.match(re))
      return true;

   displayOptionalAlert("Field was not a well formed email.", displayAlert);
   return false;
}

/**
 * Validates for a match against the regular expression provided.
 * @param {Object} fieldOrId
 * @param {Object} regularExpression - the regular expression to match against
 * @param {Object} errorMessage - the error message to display in the event of a failure
 * @param {Object} displayAlert
 */
function validateEmail(fieldOrId, regularExpression, errorMessage, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   var re = new RegExp(regularExpression);
   if(field.value.match(re))
      return true;

   displayOptionalAlert(errorMessage, displayAlert);
   return false;
}

/**
 * Validates number ranges field must be between from and to values.
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} from - minimum value allowable
 * @param {Object} to - maximum value allowable
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateRange(fieldOrId, from, to, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;
   var value = parseFloat($F(field));

   if(value >= parseFloat(from) && value <= parseFloat(to))
      return true;

   displayOptionalAlert("Field must be a number between " + from + " and " + to, displayAlert);
   return false;
}

/**
 * Validates whether a field value is less than or equal to a maximum value specified.
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} max - maximum value allowable
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateMaxValue(fieldOrId, max, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;
   var value = parseFloat($F(field));

   if(value >= parseFloat(min))
      return true;

   displayOptionalAlert("Field must be a number between " + from + " and " + to, displayAlert);
   return false;
}

/**
 * Validates whether a field value is greater than or equal to a minimum value specified.
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} min - minimum value allowable
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateMinValue(fieldOrId, min, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;
   var value = parseFloat($F(field));

   if(value <= parseFloat(min))
      return true;

   displayOptionalAlert("Field must be a number between " + from + " and " + to, displayAlert);
   return false;
}

/**
 * Validates that field is greater than or equal to a minimum length
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} length - minimum length of the field
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateMinLength(fieldOrId, length, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   if(!validateMandatory(fieldOrId) || field.value.length >= length)
      return true;

   displayOptionalAlert("Field was not the minimum length of " + length, displayAlert);
   return false;
}

/**
 * Validates that field is greater than or equal to a minimum length
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} length - maximum length of the field
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateMaxLength(fieldOrId, length, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   if(field.value.length <= length)
      return true;

   displayOptionalAlert("Field was not under the maximum length of " + length, displayAlert);
   return false;
}

/**
 * Validates that field is of a specified size range
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} from - minimum length of the field
 * @param {Object} to - maximum length of the field
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateSize(fieldOrId, from, to, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   if(field.value.length >= from && field.value.length <= to)
      return true;

   displayOptionalAlert("Field was not between the length of " + this.from + " and " + this.to, displayAlert);
   return false;
}

/**
 * Validates that the field provided contains a valid date.
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} format - date format field must conform to
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateDate(fieldOrId, format, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;
   if(isFormattedDate(field.value, format))
      return true;

   displayOptionalAlert("Please ensure that the date is valid and in the format " + format +
      ".\n\nIf required, change the date entered or clear the field and reselect using the date picker.",
      displayAlert);
   return false;
}

/**
 * validates hours for time
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} hoursInDay - 24 or 12 hour clock
 */
function validateHour(fieldOrId, hoursInDay)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

	if(!validateRange(field, 0, hoursInDay - 1,true))
	{
		setTimeout(function(){Field.focus(field)}, 30);
        return false;
	}
    return true;
}


/**
 * validates minutes for time
 * @param {Object} fieldOrId - field or the id of the field to be validated
 */
function validateMinute(fieldOrId)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

	if(!validateRange(field, 0, 59,true))
	{
		setTimeout(function(){Field.focus(field)}, 30);
        return false;
	}
    return true;
}

/**
 * Validates that two fields are equal
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} referencefieldOrId - field or the id of the field which the first field must be
 * equal to
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateEquality(fieldOrId, referencefieldOrId, displayAlert)
{
   var field = $(fieldOrId);
   var referenceField = $(referencefieldOrId);
   var value = $F(field);
   var referenceValue = $F(referenceField);
   if(value == null || trim(value) == "")
      return true;
   if(referenceValue == null || trim(referenceValue) == "")
      return true;

   if(value == referenceValue)
      return true;

   displayOptionalAlert("Field was not equal to " + referenceFieldName, displayAlert);
   return false;
}

/**
 * Validates that the field provided is a date between the from and to dates (inclusive)
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} format - format the date must to conform to
 * @param {Object} from - minimum date (inclusive)
 * @param {Object} to - maximum date (inclusive)
 */
function validateDateRange(fieldOrId, format, from, to)
{
   var field = $(fieldOrId);
   var value = $F(field);
   if(value == null || trim(value) == "")
      return true;

   //first validate that the field is a valid date
   if(!validateDate(field, format, true))
      return false;

   if(from != null && to != null)
   {
      if(compareDates(from, format,value, format) == 0 &&
	      compareDates(value,format,to,format) == 0 )
	      return true;
      else
      {
         alert("Date must be between " + from + " and " + to);
         return false;
      }
   }
   else if(from != null)
   {
      if(compareDates(value, format,from, format) == 1 ||
         value == from)
         return true;
      else
      {
         alert("Date must be equal to or after " + from);
         return false;
      }
   }
   else if(to != null)
   {
      if(compareDates(to, format,value, format) == 1 ||
         value == to)
         return true;
      else
      {
         alert("Date must be equal to or before " + to);
         return false;
      }
   }
   return true;
}

/**
 * Validates that a field does not contain any of the characters provided
 * @param {Object} fieldOrId - field or the id of the field to be validated
 * @param {Object} excludedCharacters - list of characters which must not be present in the field
 * value
 * @param {Object} displayAlert - true or false to determine if an a lert should be displayed on
 * failure.
 */
function validateExcludedCharacters(fieldOrId, excludedCharacters, displayAlert)
{
   var field = $(fieldOrId);
   if(field.value == null || trim(field.value) == "")
      return true;

   var re = new RegExp("[" + excludedCharacters + "]");
   if(!field.value.match(re))
      return true;

   displayOptionalAlert("Field cannot conatain any of the following characters: " + excludedCharacters, displayAlert);
   return false;
}

/**
 * Displays the supplied message in an alert if displayAlert is true.
 * @param {Object} message - the message to display
 * @param {Object} displayAlert - true or false to indicate if the message should be displayed.
 * If null, it defaults to false.
 */
function displayOptionalAlert(message, displayAlert)
{
   displayAlert = (displayAlert == null)? false : displayAlert;
   if (displayAlert)
   {
      alert(message);
   }
}
