/* Trim method for string */
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g, ""); 
};

function validate(form) {
	// call any user's functionality before validation

	try {
		validate_startup();
	} catch (e) {
	}
	
	var valid = true;

	// get values from tinyMCE
	try {
		tinyMCE.triggerSave();
	} catch (e) {
	}

  var elements = new Array();
	if(form.tagName.toString().toLowerCase() == 'form') {
		var elements = form.getElementsByTagName('*');
	} else {
		elements[0] = form;
		while((form.tagName.toString().toLowerCase() != 'form') && (form.parentNode != null)) {
			form = form.parentNode;
		}
		if(form.tagName.toString().toLowerCase() != 'form') {
			elements = new Array();
		}
	}
	/* Iterate through the form fields */
	for(var eCounter = 0; eCounter < elements.length; eCounter++) {
		var element = elements[eCounter];
		/* Look for validation data */
		var alt = element.getAttribute('alt')
		if((alt != null) && (alt != undefined) && (alt != '') && (element.tagName != 'IMG')) {
			/* Try to unserialize validation data */
			try {
				eval("var responseObj = " + alt);
			} catch (e) {
				continue;
			}
			
			/* Trim whitespace */
			element.value = element.value.trim();
			var elementError = false;
			var errorMessage = "";
			
			/* Look for required field and required field error message */
			var required = false;
			if(responseObj['required'] != undefined) {
				required = responseObj['required'];
			}
			if(required) {
    			var requiredMessage = 'Required field';
    			if(responseObj['required_message'] != undefined) {
    				requiredMessage = responseObj['required_message'];
    			}
    			
    			if(element.value.length == 0) {
    				elementError = true;
    				errorMessage = requiredMessage;
    			}
			}
			
			/* Look for validators */
			if((!elementError) && (element.value.length > 0) && ((responseObj['group'] == null) || (check_group_validation(form, element, responseObj['group'])))) {
				for(var vCounter=0; vCounter<responseObj['validators'].length; vCounter++) {
					if(responseObj['validators'][vCounter]['class'] != undefined) {
						var className = responseObj['validators'][vCounter]['class'];
						/* try to create a validator object */
						try {
							eval('var validator = new '+className+'()');
						} catch (e) {
//							alert('Unknown validation class: '+className);
							continue;
						}
						
						/* Attache a standard initialization method */
						validator.initialize=function(parameters) {
							try {
								for(var parameter in parameters) {
									this[parameter] = parameters[parameter];
								}
							} catch(e) {}
						}
	
						/* Initialize parameters */
						validator.initialize(responseObj['validators'][vCounter]['parameters']);
						
						/* Validate */
						errorMessage = validator.execute(element.value);
						if(errorMessage) {
		    				elementError = true;
		    				break;
						}
					}
				}
			}
			
			/* Show/Hide alerts */
			var alertImg = document.getElementById(element.name+"Error");
			if(elementError) {
				valid = false;
				try {
					my_field_error(element, errorMessage);
				} catch (e) {
					if(alertImg) {
						alertImg.alt = errorMessage;
						alertImg.title = errorMessage;
						alertImg.style.display = 'inline';
					}
				}
			} else {
				try {
					my_field_error(element, null);
				} catch (e) {
					if(alertImg) {
   						alertImg.style.display = 'none';
					}
				}
			}
		}
	}
	
	// call any user's functionality after validation
	try {
		validate_shutdown();
	} catch (e) {
	}

	return valid;
}

function check_group_validation(form, gElement, group) {
	var elements = form.getElementsByTagName('*');
	for(var eCounter = 0; eCounter < elements.length; eCounter++) {
		var element = elements[eCounter];
		/* Look for validation data */
		var alt = element.getAttribute('alt')
		if((alt != null) && (alt != undefined) && (alt != '')) {
			/* Try to unserialize validation data */
			try {
				eval("var responseObj = " + alt);
			} catch (e) {
				continue;
			}
			
			/* Trim whitespace */
			element.value = element.value.trim();
			
			if((element.value.length > 0) && (responseObj['group'] == group) && (element != gElement)) {
				return true;
			}
		}
	}
	
	return false;
}


/* Validators */

/**
 * sfStringValidator allows you to apply string-related constraints to a
 * parameter.
 *
 * Optional parameters:
 *
 * # insensitive  - [false]              - Whether or not the value check
 *                                                against the array of values is
 *                                                case-insensitive. Note:
 *                                                When using this option, values
 *                                                in the values array must be
 *                                                entered in lower-case.
 * # max          - [none]               - Maximum string length.
 * # max_error    - [Input is too long]  - An error message to use when
 *                                                input is too long.
 * # min          - [none]               - Minimum string length.
 * # min_error    - [Input is too short] - An error message to use when
 *                                                input is too short.
 * # values       - [none]               - An array of values the input
 *                                                is allowed to match.
 * # values_error - [Invalid selection]  - An error message to use when
 *                                                input does not match a value
 *                                                listed in the values array.
 */

/* Constructor */
var sfStringValidator=function() {
	this.insensitive = false;
	this.max = null;
	this.max_error = "Input is too long";
	this.min = null;
	this.min_error = "Input is too short";
	this.values = null;
	this.values_error = "Invalid selection";
}

/* Validation method */
sfStringValidator.prototype.execute=function(value) {
	if ((this.min != null) && (value.length < this.min)) {
		// too short
		return this.min_error;
	}

	if ((this.max != null) && (value.length > this.max)) {
		// too long
		return this.max_error;
	}
    
	if(this.values != null) {
		for(i = 0; i < this.values.length; i++) {
			if((this.insensitive?(this.values[i].toLowerCase()):(this.values[i])) == (this.insensitive?(value.toLowerCase()):(value))) {
				return false;
			}
		}
		
		return this.values_error;
	}

	return false;
}

/**
 * sfNumberValidator verifies a parameter is a number and allows you to apply
 * size constraints.
 *
 * Optional parameters:
 *
 * # max        - [none]                  - Maximum number size.
 * # max_error  - [Input is too large]    - An error message to use when
 *                                                 input is too large.
 * # min        - [none]                  - Minimum number size.
 * # min_error  - [Input is too small]    - An error message to use when
 *                                                 input is too small.
 * # nan_error  - [Input is not a number] - Default error message when
 *                                                 input is not a number.
 * # type       - [Any]                   - Type of number (Any, Float).
 * # type_error - [Wrong input] - An error message to use when
 *                                                 input is not a number.
 */

/* Constructor */
var sfNumberValidator=function() {
	this.max = null;
	this.max_error = "Input is too large";
	this.min = null;
	this.min_error = "Input is too small";
	this.nan_error = "Input is not a number";
	this.type = "any"; // 'any', 'decimal', 'float', 'int', 'integer'
	this.type_error = "Wrong input";
}

/* Validation method */
sfNumberValidator.prototype.execute=function(value) {
	if(isNaN(value)) {
		return this.nan_error;
	}
	
	iValue = parseInt(value, 10);
	fValue = parseFloat(value);
	
	if((this.type == 'int') || (this.type == 'integer')) {
		if(fValue != iValue) {
			return this.type_error;
		}
		pValue = iValue;
	} else {
		pValue = fValue;
	}
	form
	if((this.min != null) && (pValue < this.min)) {
		return this.min_error;
	}
	
	if((this.max != null) && (pValue > this.max)) {
		return this.max_error;
	}
	
	return false;
}

/**
 * sfRegexValidator allows you to match a value against a regular expression
 * pattern.
 *
 * Required parameters:
 *
 * # pattern - [none] - A PCRE, preg_match() style regular expression
 *                             pattern.
 *
 * Optional parameters:
 *
 * # match       - [true]          - Indicates that the pattern must be
 *                                          matched or must not match.
 * # match_error - [Invalid input] - An error message to use when the
 *                                          input does not meet the regex
 *                                          specifications.
 */

/* Constructor */
var sfRegexValidator=function() {
	this.match = true;
	this.match_error = "Invalid input";
	this.pattern = null;
}

/* Validation method */
sfRegexValidator.prototype.execute=function(value) {
	if(this.pattern != null) {
		match = Boolean(this.match);
		pos = 0;
		unescaped = "";
		while(pos < this.pattern.length) {
			c = this.pattern.charAt(pos);
			if (c == "\\") {
				pos++;
			}
			try {form
				unescaped += this.pattern.charAt(pos);
			} catch(e) {}
			pos++;
		}

		try {		
			eval("regExp = "+unescaped);
			value = String(value);
			if((value.match(regExp) && match) || (!value.match(regExp) && !match)) {
				return false;
			} else {
				return this.match_error;
			}
		} catch(e) {
			return false;
		}
	} else {
		return false;
	}
}

/**
 * sfEmailValidator verifies a parameter contains a value that qualifies as an
 * email address.
 * 
 * Optional parameters:
 *
 * # email_error - [Invalid input] - An error message to use when the
 *                                          input is not an email address
 */

/* Constructor */
var sfEmailValidator=function() {
	this.email_error = "Invalid input";
}

sfEmailValidator.prototype.execute=function(value) {
	regExp  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})$/;
	if (regExp.test(value)) {
		return false;
	} else {
		return this.email_error;
	}
}


/**
 * sfCompareValidator checks the equality of two different request parameters.
 *
 * Required parameters:
 *     check:          field2
 * 
 * Optional parameters:
 * # compare_error - [The values you entered do not match. Please try again.] - 
 *                           An error message to use when the fields do not match
 */

/* Constructor */
var sfCompareValidator=function() {
	this.check = null;
	this.compare_error = "The values you entered do not match. Please try again";
}

sfCompareValidator.prototype.execute=function(value) {
	if(this.check != null) {
		check_field = document.getElementById(this.check);
		if(check_field != null) {
			check_value = check_field.value;
			if(check_value != value) {
				return this.compare_error;
			}
		}
	}
	
	return false;
}

/**
 * sfPropelUniqueValidator validates that the uniqueness of a column.
 * 
 * Optional parameters:
 * # unique_error - [The value already exists. Please choose another one] - 
 *                           An error message to use when
 *                           the value for this column already
 *                           exists in the database.
 */
/* Constructor */
	var sfPropelUniqueValidator=function() {
	this.user_id = null;
	this.unique_error = "The values you entered do not match. Please try again";
}

sfPropelUniqueValidator.prototype.execute=function(value) {
	var user_id = '';
	if (this.user_id != null){
		user_id = $(this.user_id).value;
	}
	var querystring = 'value=' + value + '&id=' + user_id;
	var url = '/backend.php/users/uniqueValidator?' + querystring;
	var error = this.unique_error;
	
	new Ajax.Request(url, {
			method: 'post',
			asynchronous: false,
			onSuccess: function(transport) {
				if (transport.responseText != 'exist'){
					error = false;
				}
			}
		});

	return error;
}

/* Constructor Compare Dates*/


var sfDateValidator=function() 
{
    this.operator= null;
    this.date_error= "The date you entered is not valid. The correct format is YYYY-MM-DD";
    this.compare=  null;
    this.compare_between= null;
    this.operator_between= null;
    this.compare_error= "The Start Date cannot be greater than the End Date";
}

sfDateValidator.prototype.execute=function(value)
{
	//Get the date, and validate according to calendar.
     var beginDate = new String(value)
     var beginDay = new String(beginDate.substring(beginDate.lastIndexOf("-")+1,beginDate.length))  
     var beginMonth = new String(beginDate.substring(beginDate.indexOf("-")+1,beginDate.lastIndexOf("-")))  
     var beginYear = new String(beginDate.substring(0,beginDate.indexOf("-")))
     
     if (isNaN(beginYear) || beginYear.length<4 || parseFloat(beginYear)<1900)
                return this.date_error;
     
     if (isNaN(beginMonth) || parseFloat(beginMonth)<1 || parseFloat(beginMonth)>12) 
        return this.date_error;
     
     if (isNaN(beginDay) || parseInt(beginDay, 10)<1 || parseInt(beginDay, 10)>31)     
        return this.date_error;
     
     if (beginMonth==4 || beginMonth==6 || beginMonth==9 || beginMonth==11 || beginMonth==2) 
     {
         if (beginMonth==2 && beginDay > 29 || beginDay>30)
                        return this.date_error;
     }
     
    //Get the second date
    var compareDate_field = document.getElementById(this.compare);
	if (compareDate_field != null)
	{
	compareDate = compareDate_field.value;
	}
    if ( compareDate != '' )
    {
      
      var operator = (this.operator!=null)? this.operator :  '==';
      
      var endDate = new String(compareDate)
      var endDay = new String(endDate.substring(endDate.lastIndexOf("-")+1,endDate.length))  
      var endMonth = new String(endDate.substring(endDate.indexOf("-")+1,endDate.lastIndexOf("-")))  
      var endYear = new String(endDate.substring(0,endDate.indexOf("-"))) 
      
      //Make value1 and value2 in format 'YYYYMMDD' to compare each other.
      var value1 = beginYear + beginMonth + beginDay;
      var value2 = endYear + endMonth + endDay;
     
	  //Check if both values are equal. If so, clear the End Date field to be empty.
      if(value1 == value2)
      {
      	document.getElementById("events_end_date").value="";
      }
           
      // If both dates are valid, compare it. Otherwise ignore the comparison
      if ( value2 != null )
      {
        var valid = false;
        switch ( operator)
        {
          case '>':
            valid = value1 > value2;
            break;
          case '>=':
            valid = value1 >= value2;
            break;
          case '<=':
            valid = value1 <= value2;
            break;
          case '<':
            valid = value1 < value2;
            break;
          case '==':
            valid = String(value1).trim() == String(value2).trim();
            break;
        }
        if (!valid)
           return this.compare_error;
      }
    }
   return false;
}

/* RichText Validator */
function fixTextArea(saveYaml){
	elements = $$("textarea");
	elements.each(function(textarea){
		Object.keys(saveYaml).each(function(key)
		{
			if (textarea.name == key) {
				textarea.setAttribute("alt", '{"required":true,"group":null,"required_message":"'+saveYaml[key].required.msg+'","validators":{}}');
				
				divIframeContent = textarea.up();
				var richTextAlert = document.createElement('img');
				richTextAlert.setAttribute('src', '/sfFormValidationPlugin/images/alert.gif');
				richTextAlert.setAttribute('title', 'The field cannot be blank');
				richTextAlert.setAttribute('id', key+'Error');
				richTextAlert.style.display = 'none';
				divIframeContent.appendChild(richTextAlert);
				
				return true;
			}
		});
	});
	return false;
}
/* unCheck */

addEvent(window, 'DOMContentLoaded', init); 

function init() {
	  if ($('rolesToValidate')) {
	  	unCheck();
      	Event.observe($('associated_user_accesslevel_3'), 'click', unCheck.bind($('associated_user_accesslevel_3')));   
      	Event.observe($('associated_user_accesslevel_2'), 'click', unCheck.bind($('associated_user_accesslevel_2')));   
      }
}
function unCheck() {
$('rolesToValidate').getElementsBySelector('input[type="checkbox"]').each(
		function(element) {
			if ($('associated_user_accesslevel_3').checked == true || $('associated_user_accesslevel_2').checked == true) {
				element.disabled = false; 
        	}
        	else if($('associated_user_accesslevel_3').checked == false && $('associated_user_accesslevel_2').checked == false)  {
        		element.checked = false;
        		element.disabled = true; 
        	}
        	
		}
	)
}
