/*
This is a TextField class with remote validation possibility. You can specify if the validation must occur on blur or on validate.
The server must return a JSON object or boolean exactly like form validation.

true // it's all good
or
{ success: true } // it's all good
or
{success:false,
errors:'Explication text' // text display on error
}

Example
Code:

        new Ext.form.TextFieldRemoteVal({
            ... // Config object from TextField
            // New possibility
	   remoteValidation: 'onValidate', 		// When start remote validation, value: 'onBlur' or 'onValidate'
	   urlRemoteVal: 'url', 					// Url for remote validation
	   method: 'POST', 						// Optional, method for remote validation 'GET' or 'POST', default POST 
	   paramsRemoteVal: { w: 'testPseudo' }, 	// Optional, additional parameter(s) (Object or String)
	   timeout: 30, 							// Optional, timeout for validation request, default 30	
	   badServerRespText: 'My text', 			// Optional, text showing after bad server response, default: 'Error: bad server response during validation'
	   badComText: 'My text' 					// Optional, text showing after incorrect comunication, default: 'Error: validation unavailable'
        })
*/
Ext.form.TextFieldRemoteVal = function(config){
    Ext.form.TextFieldRemoteVal.superclass.constructor.call(this, config);
	if( this.urlRemoteVal ) {
		if( this.remoteValidation == 'onValidate' ) {
			this.on('valid', this.startRemoteVal.createDelegate(this));
		}else if( this.remoteValidation == 'onBlur' ) {
			this.on('blur', this.startRemoteVal.createDelegate(this));
		}
	}
};

Ext.extend(Ext.form.TextFieldRemoteVal, Ext.form.TextField, {
	remoteValidation: null, /* 'onValidate' or 'onBlur' */
	urlRemoteVal: null,
	timeout: 30,	
	method: 'POST',
	badServerRespText: 'Error: bad server response during validation',
	badComText: 'Error: validation unavailable',
	
	// redefinition 
	onRender : function(ct){
		Ext.form.TextFieldRemoteVal.superclass.onRender.call(this, ct);
		
		this.remoteCheckIcon = ct.createChild({tav:'div', cls:'x-form-remote-wait'});
		this.remoteCheckIcon.hide();
	},
	
	// private
	alignRemoteCheckIcon : function(){
        this.remoteCheckIcon.alignTo(this.el, 'tl-tr', [2, 2]);
    },
	
	// private
	getParams: function() {
        var tfp = (this.name||this.id)+'='+this.getValue();
        var p = (this.paramsRemoteVal?this.paramsRemoteVal:'');
        if(p){
            if(typeof p == "object")
                tfp += '&' + Ext.urlEncode(p);
            else if(typeof p == 'string' && p.length)
                tfp += '&' + p;
        }
		return tfp;
	},
	
	// public
	startRemoteVal: function() {
		var v = this.getValue();
		// don't start a remote validation if the value doesn't change (getFocus/lostFocus for example)
		if( this.lastValue != v ) {
			this.lastValue = v;
			if( this.transaction ) {
				this.abort();
			}
			this.alignRemoteCheckIcon();
			this.remoteCheckIcon.show();
			var params = this.getParams();
			this.transaction = Ext.lib.Ajax.request(
					            this.method,
					            this.urlRemoteVal + (this.method=='GET' ? '?' + params : ''),
					            {success: this.successRemoteVal, failure: this.failureRemoteVal, scope: this, timeout: (this.timeout*1000)},
					            params);
		}
		// but if remote validation error, show it! (because validateValue reset it)
		else if( !this.isValid ) {
			this.markInvalid(this.currentErrorTxt);
		}
	},
	
	// public
	abort : function(){
		if(this.transaction){
			Ext.lib.Ajax.abort(this.transaction);
		}
	},
	
	// private
	successRemoteVal: function(response) {
		this.transaction = null;
		this.remoteCheckIcon.hide();
		var result = this.processResponse(response);
		if(result) {
			if(result.errors) {
				this.currentErrorTxt = result.errors;
				this.markInvalid(this.currentErrorTxt);
				this.isValid = false;
			} else {
				this.isValid = true;
			}
		}else{
			this.currentErrorTxt = this.badServerRespText;
			this.markInvalid(this.currentErrorTxt);
			this.isValid = false;
		}
	},
	
	// private
	failureRemoteVal: function(response) {
		this.transaction = null;
		this.remoteCheckIcon.hide();
		this.currentErrorTxt = this.badComText;
		this.markInvalid(this.currentErrorTxt);
		this.isValid = false;
	},
	
	// private
	processResponse: function(response) {
        return (!response.responseText ? false : Ext.decode(response.responseText));
    }

});