Ext.namespace('Ext.ux', 'Ext.ux.plugins');

//Плагин для вывода подсказок формы.
Ext.ux.plugins.FormInfoTips = {
	init:function(form) {
	
		var t = new Ext.XTemplate(
			'{[this.init(values)]}',
			'<div class="x-form-item {5}" tabIndex="-1">',
				'<label {[this.qtip]} for="{0}" style="{2}" class="x-form-item-label">{1}{[this.reqFlag]}{4}',
				'{[this.img]}{[this.htmlAfterLabel]}</label>',
				'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
				'</div><div class="{6}"></div>',
			'</div>',
			{
			 init: function(vals){
			 		var f = form.findById(vals[0]);
			 		this.qtip = '';
			 		this.img = '';
			 		this.reqFlag = '';
			 		this.htmlAfterLabel = '';
			 		if (f) {
				 		if (typeof f.discripion == 'string') {
				 			this.qtip = 'ext:qtitle="' + f.fieldLabel + '" ext:qtip="' + f.discripion + '!!!" ext:qclass="empty"';
				 			this.img = '<img src="' + f.discripionImg + '"' + this.qtip + '>';
				 		}
				 		if (f.allowBlank == false) {
				 			this.reqFlag = '*';
				 		}
				 		
				 		if (typeof f.htmlAfterLabel == 'string') {
				 			this.htmlAfterLabel = f.htmlAfterLabel;
				 		}
				 	}
			 		return '';
			 }
			}
		);
		
		t.disableFormats = true;
		t.compile();
		
		form.layoutConfig = form.layoutConfig || {};
		Ext.apply(form.layoutConfig, {
			fieldTpl: t
		});
	}
}

//Плагин для удалённой валидации полей
Ext.ux.plugins.RemoteValidator = {
	init:function(field) {
		// save original functions
		var isValid = field.isValid;
		var validate = field.validate;
		var markInvalid = field.markInvalid;
 		this.lastValue = '';
		// apply remote validation to field
		Ext.apply(field, {
				remoteValid:false,
				requestExecuting: true,
 				isValid:function(preventMark) {
					return isValid.call(this, preventMark) && !this.requestExecuting && this.remoteValid;
				},
 				validate:function() {
					if(!validate.call(this)) {
						this.remoteValidationTask.cancel();
						this.hideLoadingMask();
						return false;
					}

					if (this.requestExecuting) {
						return false;
					}
					else {
						if(this.remoteValid) {
							this.markValid();
							return true;
						}
						else {
							this.markInvalid(this.reason);
							return false;
						}
					}

					return false;
				},

				getVlmLeftPos: function() {
					if (Ext.isIE)
						return this.width;
					else
						return this.getEl().getOffsetsTo(this.getEl().parent())[0] + this.getEl().getWidth() + 2;
				},
 
				markValid: function() {
					this.clearInvalid();
					
					if (!this.validMarked){
						this.validMarked = Ext.DomHelper.append(this.getEl().parent(), {
							cls:'x-form-valid-icon',
							style: 'left:' + this.getVlmLeftPos()
						}, true)
					}
				},
 
 				unMarkValid: function() {
					if (this.validMarked) {
						this.validMarked.remove();
						delete this.validMarked;
					}
 				},
 
 				markInvalid: function(reason) {
 					this.unMarkValid();
 					markInvalid.call(this, reason);
 				},
 
 				showLoadingMask: function() {
					this.requestExecuting = true;
					this.clearInvalid();
					this.unMarkValid();							

					if (!this.validLoadMask){
						this.validLoadMask = Ext.DomHelper.append(this.getEl().parent(), {
							cls:'x-form-loading-icon',
							style: 'left:' + this.getVlmLeftPos()
						}, true)
					}
 				},
 
 				hideLoadingMask: function() {
 					this.requestExecuting = false;
					if (this.validLoadMask) {
						this.validLoadMask.remove();
						delete this.validLoadMask;
					}
 				},
 
				// private - remote validation request
				validateRemote:function() {
					if (this.lastValue != this.getRawValue()) {
						this.rvOptions.params = this.rvOptions.params || {};
						this.rvOptions.params.field = this.name;
						this.rvOptions.params.value = this.getValue();
						this.showLoadingMask();
						this.remoteValid = false;
						this.lastValue = this.getRawValue();
						Ext.Ajax.request(this.rvOptions);
					}
				},
 
				// private - remote validation request success handler
				rvSuccess:function(response, options) {
					this.hideLoadingMask();
					var o;
					//TODO поставить проверки без Exteption
					try {
						o = Ext.decode(response.responseText);
					}
					catch(e) {
						//throw this.cannotDecodeText;
						return false
					}
					
					if('object' !== typeof o) {
						//throw this.notObjectText;
						return false
					}
					if(true !== o.success) {
						//throw this.serverErrorText + ': ' + o.error;
						return false
					}
					
					var names = this.rvOptions.paramNames;
					this.remoteValid = true === o[names.valid];
					this.reason = o[names.reason];
					this.validate();
				},
 
				// private - remote validation request failure handler
				rvFailure:function(response, options) {
					this.hideLoadingMask();
					//throw this.requestFailText
					return false
				},
 
				// private - runs from keyup event handler
				filterRemoteValidation:function(e) {
					if(!e.isNavKeyPress()) {
						this.requestExecuting = true;
						this.clearInvalid();
						this.unMarkValid();	
						this.remoteValidationTask.delay(this.remoteValidationDelay);
					}
				},
				
				// private - runs from field value changed event handler
				forceRemoteValidation:function(e) {
					this.remoteValidationTask.delay(0);
				}
		});
 
		// remote validation defaults
		Ext.applyIf(field, {
				remoteValidationDelay:500,
				reason:'Server has not yet validated the value',
				cannotDecodeText:'Cannot decode json object',
				notObjectText:'Server response is not an object',
				serverErrorText:'Server error',
				requestFailText:'Server request failed'
		});
 
		// install event handlers on field render
		field.on({
				render:{single:true, scope:field, fn:function() {
					this.remoteValidationTask = new Ext.util.DelayedTask(this.validateRemote, this);
					this.el.on({
						'keyup': this.filterRemoteValidation,
						'change': this.forceRemoteValidation,
						scope: this
					})
				}}
		});
 
		// setup remote validation request options
		field.rvOptions = field.rvOptions || {};
		Ext.applyIf(field.rvOptions, {
				method:'post',
				scope: field,
				success: field.rvSuccess,
				failure: field.rvFailure,
				paramNames: {
					valid:'valid'
					,reason:'reason'
				}
		});
	}
};