/**
 * @author Barrington Henry
 */

/**
 * script taken from mozilla development
 * @param {Object} fun
 * @param {Object}  thisp
 * 
 */
if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var res = [];
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}

var GM_Validation = Class.create();
GM_Validation.prototype = {
	validationdefinitions:{
		'required':['This is a required field.','client', function(v) {
				return !v.blank();
			}],
		'validate-isexist':['sdasd','server', function(v, elem) {
				inputObj = {
					typeexist:elem.identify(), 
					value:v
				};
				this.ajaxInProgress = true;
				this.doAlert('progress', elem, 'checking availability');
				var processInfo = new AJAXgetinfo('checkexistence',{source:'/gmasync/utils'},{pars:inputObj});
				AJAXgetinfo.addMethods({
					afterProcess:function(transport){
						var response = transport.responseText;
						var jsoneval = response.evalJSON();	
						var keywordHint = jsoneval.fullhtml;
					
						this.error = keywordHint;
						this.validationdefinitions['validate-isexist'][0] = keywordHint;

						if(jsoneval.resp == 'exists'){
							this.ajaxInProgress = false;							
							this.ajaxresults.set(elem.identify(), false);
							
						}else{
							this.ajaxInProgress = false;
							this.ajaxresults.set(elem.identify(), true);				
						}
					}.bind(this)
				});
				processInfo.getinfoGen2();
				return false;
		}],
		'validate-email': ['Please enter a valid email.','', function (v) {
				return  /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
			}]
	},
	elem_validator_key:'elem_validators',
	activevalidatedef:'present',
	element_value_cache_id:'cacheid',
	intervalmappings:$H(),
	ajaxresults:$H(),
	validatedElements:[],
	initialize : function(form, options){
		this.options = Object.extend({
			onSubmit : true,
			stopOnFirst : false,
			ajaxInProgress:false,
			clearErrors : true,
			immediate : false,
			focusOnError : true,
			useTitles : false,
			messageOverlibInset:'body',
			onFormValidate : function(result, form) {},
			onElementValidate : function(result, elm) {},
			changeDefaultAnchorPosition:false,
			defaultAnchorPosition:{}
		}, options || {});
		this.form = $(form);
		
		if(this.options.onSubmit) Event.observe(this.form,'submit',this.onSubmit.bind(this),false);	
		this.overlib = new GM_overlib({insertinto:this.options.messageOverlibInset});
		if(this.options.immediate) {		
			Form.getElements(this.form).each(function(input) {
				var cn = input.classNames();
				
				var valid_validators = $A(cn).filter(this.isAValidator.bind(this));	
				
				if(valid_validators.size() > 0){
					input.store(this.elem_validator_key, valid_validators);
					Event.observe(input, 'blur', function(ev) { 
												this.validate(input); 												
											}.bind(this));
				}
			}.bind(this));
		}
	},
	validate:function(input){		
		var definitions = $A(input.retrieve(this.elem_validator_key));
		var v = input.value;
		var valuecache = input.retrieve(this.element_value_cache_id);
		
		this.validatedElements.push(input);
	
		if(valuecache != undefined){
			if(valuecache == v){
				return;
			}
		}
		
		var result = definitions.all(function(defs){
			input.store(this.activevalidatedef, defs);
			return this.validationdefinitions[defs][2].apply(this, [v, input]);
		}.bind(this));
				
		if(!this.ajaxInProgress){
			this.processAlert.apply(this, [result, input]);
		}else{
			var interval = window.setInterval(function(){
						if(!this.ajaxInProgress){
							var result = this.ajaxresults.get(input.identify());
							this.processAlert.apply(this, [result, input]);
							window.clearInterval(this.intervalmappings.get(input.identify()));
						}
				}.bind(this), 100);
				this.intervalmappings.set(input.identify(), interval);			
		}
		
		input.store(this.element_value_cache_id, v);
	},
	isAValidator:function(element, index, array){
		return !Object.isUndefined(this.validationdefinitions[element]);
	},
	doAlert:function(type,input, message){
		var anchorelem = null;
		
		if (this.options.changeDefaultAnchorPosition) {
			input.siblings().each(function(elem){
				if ((this.options.defaultAnchorPosition.posclass != undefined) && 
					elem.hasClassName(this.options.defaultAnchorPosition.posclass)) {
					anchorelem = elem;
				}
			}.bind(this));
		}else{
			anchorelem = input;
		}
		
		this.overlib.generateoverlib({},
			{	bubbleselect:type, 
				innercontent:message, 
				elem:anchorelem, 
				bubbleidpostfix:anchorelem.identify(),
				regex:anchorelem.identify(),
				margincumul:10
			}
		);	
	},
	processAlert:function(result, input){
		if(!result){
			presentdefinition = input.retrieve(this.activevalidatedef);

			message = this.validationdefinitions[presentdefinition][0];
			this.doAlert('notok', input, message);
		}else{
			message = 'ok';
			this.doAlert('ok', input, message);
		}
	},
	
	refresh:function(){
		this.validatedElements.each(function(elements){
			elements.store(this.element_value_cache_id, '__this_has_been_deactivated__');
		}.bind(this));
		
		this.overlib.refresh();
		this.validatedElements = [];
	}
}