Ext.define("Ext.ux.form.field.ComboSql", {
	extend: "Ext.form.field.ComboBox",
	alias: "widget.combosql",

	config: {
		action: "searchRow",
		columns: "",
		schema: "",
		table: "",
		valueColumn: "",
		keyColumn: "",
		options: null,
		cte: false,
		where: "",
		displayField: "key",
		valueField: "value",
		triggered: false,
		params: null,
		url: "",
		rootProperty: "rows",
		totalProperty: "totalProperty",
		actionMethods: {}
	},

	queryParam: "search",

	queryCaching: false,

	triggers: {
		clear: {
			cls: Ext.baseCSSPrefix + "form-clear-trigger",
			weight: 1,
			handler: "onClearClick",
			hidden: true,
			scope: "this"
		},
		picker: {
			weight: 2,
			handler: "onTriggerClick",
			scope: "this"
		}
	},

	listeners: {
		afterrender: {
				fn: function (i_self) {
					var value = i_self.getValue();
					if (i_self.inputEl) {

						i_self.setIconCls("x-ux-search-icon");

						if (!value) {
							i_self.getTrigger("clear").hide();
						}
						else {
							i_self.getTrigger("clear").show();
						}

						if (i_self.readOnly) {
							i_self.setIconCls("");
							i_self.getTrigger("clear").hide();
						}
					}
				},
				single: true
			},
		change: {
			fn: function(i_self, value) {
				if (i_self.inputEl) {
					if (!value || (value && value.length === 0)) {
						i_self.allQuery = "";
						i_self.clearValue();
						i_self.getTrigger("clear").hide();
					}
					else {
						i_self.allQuery = i_self.lastQuery;
						if (!i_self.readOnly) {
							i_self.getTrigger("clear").show();
						}
					}
				}
			}
		}
	},

	initComponent: function() {

		var i_self = this;

		var o_actionMethods = i_self.getActionMethods() || {};

		Ext.applyIf(o_actionMethods, {
			create: "POST",
			read: "POST",
			update: "PATCH",
			destroy: "DELETE"
		});

		Ext.apply(i_self, {
			queryMode: "remote",
			displayField: i_self.getDisplayField(),
			valueField: i_self.getValueField(),
			triggerAction: "all",
			minChars: 1,
			typeAhead: false,
			maxLength: 1000,
			displayTpl: i_self.getDisplayTemplate(),
			tpl: i_self.getItemTemplate()
		});

		var o_options = i_self.getOptions() || {};

		Ext.applyIf(o_options, {
			library: i_self.getSchema(),
			file: i_self.getTable()
		});

		var i_model;

		if (o_options.schema && o_options.table) {
			if (Ext.ClassManager.isCreated(Ext.dynapp.util.Service.getModelName(o_options))) {
				i_model = Ext.ClassManager.get(Ext.dynapp.util.Service.getModelName(o_options));
			}
			else {
				i_model = Ext.define(Ext.dynapp.util.Service.getModelName(o_options), {
					extend: "Ext.data.Model",
					fields: [
						{ name: i_self.getDisplayField(), type: "auto" },
						{ name: i_self.getValueField(), type: "auto" }
					],
					idProperty: i_self.getValueField(),
					proxy: {
						url: Ext.dynapp.util.Service.getPath(o_options),
						type: "ajax",
						paramsAsJson: true,
						actionMethods: {
							read: "POST"
						},
						reader: {
							type: "json",
							rootProperty: "rows",
							totalProperty: "totalProperty"
						}
					}
				});
			}
		}
		else {
			i_model = Ext.define(ip2.unique("sqlcombo-"), {
				extend: "Ext.data.Model",
				fields: [
					{ name: i_self.getDisplayField(), type: "auto" },
					{ name: i_self.getValueField(), type: "auto" }
				],
				idProperty: i_self.getValueField(),
				proxy: {
					url: i_self.getUrl(),
					type: "ajax",
					paramsAsJson: o_actionMethods.read == "POST",
					actionMethods: o_actionMethods,
					reader: {
						type: "json",
						rootProperty: i_self.getRootProperty(),
						totalProperty: i_self.getTotalProperty()
					}
				}
			});
		}

		var i_store = Ext.create("Ext.data.Store", {
			model: i_model,
			remoteSort: true,
			autoLoad: false,
			autoSync: false,
			pageSize: 100
		});

		i_store.on({
			beforeload: {
				fn: function(i_store, i_operations) {

					var s_value = i_self.getValue() || "";
					var i_proxy = i_store.getProxy();
					var o_extraParams = i_proxy.getExtraParams();

					Ext.apply(o_extraParams, {
						action: i_self.getAction(),
						search: "",
						columns: i_self.getColumns(),
						start: 0,
						limit: 100,
						cte: i_self.getCte()
					});

					Ext.Object.merge(o_extraParams, i_self.getParams(), i_self.getExtraParams());

					if (o_extraParams.where) {
						delete o_extraParams.where;
					}

					var o_params = i_operations.getParams() || {};

					if (i_self.getCte() && s_value) {
						o_extraParams.where = i_self.getDisplayField() + " like '%" + s_value + "%'";
						delete o_extraParams.search;
						delete o_params.search;
					}
					else if (i_self.getValueColumn() && !o_params.search) {
						o_extraParams.where = i_self.getValueColumn() + " = '" + s_value + "'";
						delete o_extraParams.search;
						delete o_params.search;
					}
				}
			}
		});

		i_self.store = i_store;
		i_self.callParent();

		return i_self;
	},

	getExtraParams: function() {

		var i_self = this;
		return i_self.params || {};
	},

	initValue: function() {

		var i_self = this;

		var value = i_self.value;

		var a_loaded = [];

		if (Ext.isEmpty(value)) {
			value = null;
		}

		var a_values = Ext.Array.from(value);

		var n_load = a_values.length;

		var i_store = i_self.getStore();

		if (n_load) {

			var i_proxy = i_store.getProxy();
			var o_extraParams = i_proxy.getExtraParams();

			o_extraParams[i_self.getValueField()] = value;

			i_store.load({
				callback: function(a_records, i_store) {

					i_self.suspendCheckChange++;
					i_self.setValue(value);
					i_self.suspendCheckChange--;
					i_self.originalValue = i_self.lastValue = i_self.getValue();
					i_self.resetOriginalValue();

					delete o_extraParams[i_self.getValueField()];

					i_proxy.setExtraParams(o_extraParams);
				}
			});
		}
		else {
			i_self.originalValue = i_self.lastValue = i_self.getValue();
			i_self.resetOriginalValue();
		}
	},

	onTriggerClick: function() {

		var i_self = this;
		i_self.setTriggered(true);
		i_self.queryCaching = false;
		i_self.callParent(arguments);
	},

	getWhereTemplate: function(o_options) {

		var i_self = this;
		var o_values = {
			library: o_options.library,
			file: o_options.file
		};
		var i_tpl = Ext.create("Ext.XTemplate",
			"<tpl>",
				i_self.getWhere(),
			"</tpl>"
		);

		var i_compiled = i_tpl.compile();
		return i_compiled.apply(o_values);
	},

	getDisplayTemplate: function() {

		var i_self = this;

		var s_displayField = i_self.getDisplayField();

		var i_template = Ext.create("Ext.XTemplate",
			"<tpl for=\".\">",
				"{[this.renderer(values ? values[\"" + s_displayField + "\"] : \"\")]}",
			"</tpl>",
			{
				renderer: function(value) {
					return ip2.i18n(value);
				}
			}
		);
		return i_template;
	},

	getItemTemplate: function() {

		var i_self = this;

		var s_displayField = i_self.getDisplayField();

		var i_template = Ext.create("Ext.XTemplate",
			"<tpl for=\".\">",
				"<li role=\"option\" class=\"x-boundlist-item\">",
					"{[this.renderer(values ? values[\"" + s_displayField + "\"] : \"\")]}",
				"</li>",
			"</tpl>",
			{
				renderer: function(value) {
					return ip2.i18n(value);
				}
			}
		);
		return i_template;
	},

	onClearClick: function () {

		var i_self = this;

		i_self.setSelection(null);
		i_self.clearValue();

		return i_self;
	}
});
