/**
 * Pretty Accessible Forms
 * JavaScript AjaxValidation Library
 * Extends the Validation Library with an Ajax Validation
 * @version 1.0
 * @see Validation
 */
Object.extend(Validation, {
	/**
	 * Check the validity of a field via an Ajax call
	 * Because of the asynchronous nature of Ajax calls, these must be made whenever the value changes
	 * Options are "onblur" or "onkeyup". Subsequently, the Ajax function will assign the
	 * validity to the corresponding element. The Validation method will then only check this property.
	 * @param {String} className: Class Name of the custom Form validator
	 * @param {String} error: Error message for the custom validation
	 * @param {String} id: ID of the field that is to be observed
	 * @param {String} url: Server URL used for validation. The field's value will be appended to this URL.
	 *   Example: /checkUser?username=
	 * @since 1.0
	 */
	addAjax: function(className, error, id, url) {
		
		// Assign options
		var options = {
			fieldName : id,
			serverUrl : url
		};
		
		if(options.fieldName == '' || options.serverUrl == '')
		{
			return;
		}
		
		/**
		 * This function will do the actual server validation. 
		 * Called by the Validation method
		 * @param {Object} v The value of the field
		 * @param {Object} el The field that is validated
		 */
		var checkServerValidation = function(v, el) {					
					if(el['valid-serverside'] == true	) {
						return true;
					} else if(el['valid-serverside'] == false){
						return false;
					}
					return true;
			}		
		/**
		 * Server-side validation function
		 * @param {Object} ev The event that raised that validation call
		 */
		var validateAtServer = function(ev) {
			var elm = Event.element(ev);
			var v = elm.value;
			
			var validationDone = function(r)
			{
				if(v == "") {
						elm.removeClassName('validation-failed');
						elm.removeClassName('validation-passed');
				} else {
					if( r.responseText.indexOf("true") >= 0 ) {
						elm.removeClassName('validation-failed');
						elm.addClassName('validation-passed');
						elm['valid-serverside'] = true;
					} else {
						elm.addClassName('validation-failed');
						elm.removeClassName('validation-passed');
						elm['valid-serverside'] = false;
					}
				}
			}
			
			// Ajax call to validate the field
			new Ajax.Request( options.serverUrl + v, 
				{
					method: 'get',
					Asynchronous: false,
					onComplete: validationDone
				}
			);
		}

		// Add the validation for the custom field.
		Validation.add(
			className,
			error, 
			checkServerValidation,
			options
		);

		// Observe the "keyup" event on the field --> This will be verified
		Element.observe(
			options.fieldName,
			'keyup',
			validateAtServer
		);
	}
});

// Custom validation for password field
Validation.add(
	'validate-password',					// Validation for password fields
	'Please enter a password with letters (a-z, A-Z), numbers (0-9) and at least one of (!#). Example: Th1s!sMyPassword',
	function(v){							// Validation function. v = value.
											// Check for [0-9] [a-z] [A-Z] and [!#] at least 
		return Validation.get('IsEmpty').test(v) || 
			(/^[0-9a-zA-Z!#]+$/.test(v) &&	// All characters can be in the pw 
			 /^.*[!#]+.*$/.test(v) &&		// At least one of ! or #
			 /^.*[0-9]+.*$/.test(v) &&		// At least one number
			 /^.*[a-zA-Z]+.*$/.test(v)		// At least one of [a-z,A-Z]
			 );
	}				
);

// Custom validation for fields whose values must match.
Validation.add(
	'validate-verification',
	'This value does not match its counterpart. Please verify that they match.',
	function(v, el) {
		var name = null;
		
		// Try to get the name of the element that's to be validated
		if(el.name && el.name != "") {
			name = el.name;	// By Name
		} else if(el.id && el.id != "") {
			name = el.id;	// By ID
		}
		if(name) {
			var p = name.indexOf("-verification");
			var ver;
			
			// The opposite field must be named "...-verification", e.g. password and password-verification
			if(p >= 0) {
				name = name.substring(0, p);		
			} else {
				name = name + "-verification";
			}
			ver = $F(name);
			return (v === ver);
		} else {
			return false;	// If the second field does not exist, we fail
		}
	}
);

/**
 * POPUP_FEATURES defines what will go into the popup. Can be overriden
 */
var POPUP_FEATURES = 'height=500,width=690,toolbar=no,status=no,resizable=yes,scrollbars=yes';

/**
 * initPopUps adds an unobtrusive JavaScript that will open a popup window 
 * based on the "rel" attribute of links. Any other "onclick" handler will be removed!
 * No external dependencies. Must be called after "window.load".
 * @param {String} features: String containing the features for the popup window
 */
var initPopUps = function(features) {
	// Override POPUP_FEATURES?
	if(!features) {
		features = POPUP_FEATURES;	
	}

	if (!document.getElementsByTagName){ return; }
	var anchors = document.getElementsByTagName("a");

	// loop through all anchor tags
	for (var i=0; i < anchors.length; i++){
		var anchor = anchors[i];
		if (anchor.getAttribute("href")) {
			var rel = anchor.getAttribute("rel");
			if(rel && rel.indexOf("popup" >= 0)) {
				
				// TODO: Put some more information in the rel attribute (window title, size, etc)
				anchor.onclick = function () {
						window.open(this.href, "popup", features);
						return false;
				}	
			}
		}
	}
} 