Ext.define("Ext.ux.form.field.EntityComboBox", {

	extend: "Ext.form.field.ComboBox",

	alias: [
		"widget.entitycombo",
		"widget.entitycombobox",
		"widget.entitypicker",
		"widget.ux.form.field.entitycombobox"
	],

	iconCls: "x-ux-search-icon",
	pageSize: 20,
	queryParam: "search",
	queryMode: "remote",
	typeAhead: true,
	minChars: 1,
	triggerAction: "all",
	forceSelection: false,
	cancelSearch: false,
	queryCaching: false,

	cls: "x-ux-field-entitycombobox",

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

	lastQuery: "",

	config: {
		customFilter: null,
		dmd: "",
		entity: "",
		view: "portfolio",
		context: "grid",
		extraParams: null,
		columns: [],
		model: null,
		union: null,
		unions: [],
		stored: null,
		allowAdd: false,
		changeOnLoad: false
	},

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

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

					if (Ext.isEmpty(value)) {
						i_field.getTrigger("clear").hide();
					}
					else {
						i_field.getTrigger("clear").show();
					}

					if (i_field.readOnly) {
						i_field.setIconCls("");
						i_field.getTrigger("clear").hide();
						i_field.getTrigger("new").hide();
					}
					else {
						i_field.getTrigger("new")[i_field.getAllowAdd() ? "show" : "hide"]();
					}
				}
			},
			single: true
		},
		change: {
			fn: function (i_field, value) {
				if (i_field.inputEl) {

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

					if (a_values.length === 0) {
						i_field.allQuery = "";
						i_field.clearValue();
						i_field.getTrigger("clear").hide();
					}
					else {
						i_field.allQuery = i_field.lastQuery;
						if (!i_field.readOnly) {
							i_field.getTrigger("clear").show();
						}
					}
				}
			}
		},
		enable: {
			fn: function (i_field) {

				var s_value = i_field.getValue();

				i_field.getTrigger("clear")[s_value ? "show" : "hide"]();

				i_field.getTrigger("new")[i_field.getAllowAdd() ? "show" : "hide"]();

				i_field.setIconCls("x-ux-search-icon");
			},
			buffer: 10
		},
		disable: {
			fn: function (i_field) {
				i_field.setIconCls("");
				i_field.getTrigger("clear").hide();
				i_field.getTrigger("new").hide();
			},
			buffer: 10
		},
		writeablechange: {
			fn: function (i_field, b_readOnly) {

				var s_value = i_field.getValue();
				var b_allowAdd = i_field.getAllowAdd();

				i_field.setIconCls(!b_readOnly ? "x-ux-search-icon" : "");

				i_field.getTrigger("clear")[b_readOnly || !s_value ? "hide" : "show"]();

				i_field.getTrigger("new")[b_readOnly ? "hide" : "show"]();

				if (!b_readOnly) {
					i_field.getTrigger("new")[b_allowAdd ? "show" : "hide"]();
				}


			},
			buffer: 10
		},
		autosize: {
			fn: function (i_field) {
				var i_picker = i_field.getPicker();
				i_picker.setWidth(i_field.bodyEl.getWidth());
			},
			buffer: 1
		}
	},

	overloadConfig: function (o_config) {

		if (Ext.isObject(o_config.dmd)) {

			var o_dmd = o_config.dmd;

			if (o_dmd.extraParams) {
				o_config.extraParams = o_dmd.extraParams;
			}
			if (o_dmd.pageSize) {
				o_config.pageSize = o_dmd.pageSize;
			}
			if (o_dmd.uiName) {
				o_config.view = o_dmd.uiName;
			}
			if (o_dmd.view) {
				o_config.view = o_dmd.view;
			}

			o_config.entity = o_dmd.entity;
			o_config.dmd = o_dmd.file;
		}
	},

	initComponent: function () {

		var i_self = this;
		var o_config = Ext.apply({}, i_self.initialConfig);

		i_self.overloadConfig(o_config);

		Ext.apply(i_self, ip2.pick(o_config, [
			"dmd",
			"entity",
			"view",
			"extraParams",
			"pageSize"
		]));

		i_self.store = i_self.createStore(o_config);

		i_self.initDefinitions();

		i_self.callParent(arguments);

		return i_self;
	},

	initDefinitions: function () {

		var i_self = this;

		Ext.apply(i_self, {
			tpl: i_self.getDisplayTemplate(),
			displayTpl: i_self.getTemplate()
		});
	},

	initValue: function () {

		var i_self = this;

		var value = i_self.value || null;
		var a_temp = [];

		if(Ext.isArray(value)) {
			value = Ext.Array.from(value).filter(function(value){
				return !Ext.isEmpty(value);
			});
		}

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

		i_self.setUnion(null);

		if (value) {

			if (Ext.isString(value)) {
				a_temp = value.split(",");
			}
			else {
				a_temp = Ext.Array.from(value);
			}
		}

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

		var n_load = a_values.length;

		var i_store = i_self.getStore();

		if (n_load) {

			var a_result = [];

			Ext.Array.each(a_values, function (value) {
				if (Ext.isString(value)) {
					value = "'" + value + "'";
				}
				a_result.push(value);
			});

			var s_where = i_self.valueField + " in (" + a_result.join(",") + ")";

			var o_extraParams = i_store.extraParams = i_store.extraParams || {};

			var s_tempWhere = o_extraParams.where || "";

			Ext.apply(o_extraParams, {
				where: s_where
			});

			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.value = value;
					i_self.checkDirty();

					o_extraParams.where = s_tempWhere;
				}
			});
		}
		else {
			i_self.suspendCheckChange++;
			i_self.setValue(null);
			i_self.suspendCheckChange--;
			i_self.originalValue = i_self.lastValue = i_self.value = null;
			i_self.checkDirty();
		}
	},

	validateValue: function (value) {

		var i_self = this;
		var errors = i_self.getErrors(value);
		var isValid = Ext.isEmpty(errors);

		i_self[isValid ? "clearInvalid" : "markInvalid"](errors);

		return isValid;
	},

	createStore: function (o_config) {

		var i_self = this;
		var o_store;
		var i_store;
		var b_autoLoad = true;

		var s_dmd = i_self.getDmd();
		var s_entity = i_self.getEntity();

		var o_info = ip2.dmd.getInfo({
			dmd: s_dmd,
			entity: s_entity
		});

		var o_entity = o_info.entity;

		var s_idColumn = i_self.valueField || o_entity.idColumn;

		if (!s_idColumn) {
			var a_primary = o_entity.primaryKey || [];

			s_idColumn = a_primary.join("_");
		}

		i_self.valueField = s_idColumn || "id";

		if (o_config.hasOwnProperty("autoLoad")) {
			b_autoLoad = o_config.autoLoad;
		}

		var o_settings = ip2.pick(o_config, [
			"dmd",
			"entity",
			"view",
			"extraParams",
			"pageSize",
			"context"
		]);

		o_settings.context = o_settings.context || "grid";

		o_store = Ext.apply({
			remoteSort: true,
			autoLoad: false,
			autoAbort: true
		}, o_settings);

		if (o_store.extraParams) {

			var o_extraParams = o_store.extraParams;

			if (o_extraParams.filter) {
				if (i_self.getCustomFilter()) {
					o_extraParams.filter.push(i_self.getCustomFilter());
				}
			}

			Ext.Object.each(o_extraParams, function (s_key, value) {
				o_store.extraParams[s_key] = typeof value == "object" && value !== null ? Ext.encode(value) : value;
			});
		}

		i_store = Ext.create("Ext.ux.data.dmd.Store", o_store);

		i_store.on({
			load: {
				fn: function (store, a_records) {

					if (i_self.getChangeOnLoad()) {
						i_self.fireEvent("change", i_self, value);
					}
				}
			},
			beforeload: {
				fn: function (i_store, i_operation) {

					var i_proxy = i_store.getProxy();
					var o_extraParams = i_proxy.getExtraParams();
					var a_union = i_self.getUnion();
					var o_model = i_store.dmdObject.model;
					var a_entities = o_model.entities;
					var o_entity = Ext.Array.findBy(a_entities, function (o_value) {
						return o_value.name == i_self.getEntity();
					});
					var o_view = o_entity.ui.grids[i_self.getView()];
					var o_extra = i_store.extraParams = i_store.extraParams || {};

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

					delete o_extraParams.where;

					i_store.setUnion(a_union);
					Ext.apply(o_extraParams, o_extra);

					if (o_view.wheres && o_params.search) {
						o_extraParams.where = i_self.getWhere();
						delete o_params.search;
					}

					if (o_entity.language) {
						o_extraParams.languageColumn = o_entity.language.column;
						o_extraParams.language = o_extraParams.language = ip2.navigator.user.settings.language || "en";
					}

					if (o_extraParams.hasOwnProperty("language")) {
						o_extraParams.language = ip2.navigator.user.settings.language || "en";
					}
				}
			}
		});

		var i_model = i_store.getModel();

		i_self.setModel(i_model);

		return i_store;
	},

	getWhere: function () {

		var i_self = this;
		var i_store = i_self.getStore();
		var o_model = i_store.dmdObject.model;
		var a_entities = o_model.entities;
		var s_view = i_self.getView();

		var o_entity = Ext.Array.findBy(a_entities, function (o_value) {
			return o_value.name == i_self.getEntity();
		});

		var value = i_self.getRawValue();
		var s_where = "";
		var o_view = o_entity.ui.grids[s_view];

		if (o_view.wheres && value) {

			var a_search = value.split(" ");
			var a_where = [];

			Ext.Array.each(a_search, function (s_key) {
				a_where.push("" + o_view.wheres + "" + " like '%" + s_key + "%'");
			});
			s_where = a_where.join(" AND ");
		}
		return s_where;
	},

	onBindStore: function (i_store, o_initial) {
		var i_self = this;
		i_self.callParent(arguments);

		var i_pickerSelectionModel = i_self.pickerSelectionModel;

		i_pickerSelectionModel.deselectOnContainerClick = false;
	},

	createPicker: function () {

		var i_self = this;
		var i_picker;

		var o_options = Ext.apply({
			xtype: "boundlist",
			pickerField: i_self,
			selectionModel: i_self.pickerSelectionModel,
			floating: true,
			hidden: true,
			store: i_self.getStore(),
			preserveScrollOnRefresh: true,
			pageSize: i_self.pageSize,
			tpl: i_self.tpl,
			listeners: {
				resize: {
					fn: function () {

						var i_self = this;
						var i_toolbar = i_self.pagingToolbar;

						if (i_self.rendered && i_toolbar && i_toolbar.rendered) {

							if (i_self.getStore().getTotalCount() <= i_self.pageSize) {
								i_self.el.last().setSize(null, 0);
								i_self.pagingToolbar.el.setVisible(false, false);
							}
							else {
								i_toolbar.setSize(null, null);
								i_self.el.last().setSize(null, null);
							}
						}
					}
				}
			},
			createPagingToolbar: function () {
				var i_toolbar = Ext.widget("pagingtoolbar", {
					itemId: "pagingToolbar",
					pageSearch: false,
					pageSizeEdit: false,
					store: i_self.getStore(),
					border: false,
					displayInfo: true
				});

				i_self._toolbar = i_toolbar;

				return i_toolbar;
			}
		}, i_self.listConfig, i_self.defaultListConfig);

		i_picker = i_self.picker = Ext.widget(o_options);
		i_picker.navigationModel.navigateOnSpace = false; // THIS DISABLES SELECT ON SPACE...

		if (i_self.pageSize) {
			i_picker.pagingToolbar.on("beforechange", i_self.onPageChange, i_self);
		}

		if (!i_picker.initialConfig.maxHeight) {
			i_picker.on({
				beforeshow: i_self.onBeforePickerShow,
				scope: i_self
			});
		}

		i_picker.getSelectionModel().on({
			"beforeselect": i_self.onBeforeSelect,
			"beforedeselect": i_self.onBeforeDeselect,
			scope: i_self
		});

		return i_picker;
	},

	onAddClick: function () {

		var i_self = this;

		var o_size = ip2.getWindowSize();

		var i_window = Ext.widget("window", {
			width: o_size.width * 0.6,
			height: o_size.height * 0.6,
			layout: "fit",
			border: false
		});

		var i_entityForm = Ext.widget("entityform", {
			dmd: i_self.getDmd(),
			entity: i_self.getEntity(),
			view: i_self.getView(),
			keys: {},
			action: "new",
			dataParent: i_window,
			transactiontype: i_self.getEntity(),
			activeTabIndex: 0,
			closable: false,
			buttons: [
				{
					xtype: "button",
					text: "Save",
					iconCls: "pf-floppy_disk",
					handler: function (i_button) {

						i_window.setLoading(true);

						var i_entityForm = i_button.up("entityform");

						if (i_entityForm) {
							i_entityForm.save(function (i_record) {

								i_self.loadNewRecord(i_record, function (o_data) {

									var i_store = i_self.getStore();
									i_store.loadData([o_data], true);
									i_self.setValue(i_record.get(i_record.idProperty));
									i_window.setLoading(true);
									i_window.close();
								});
							});
						}
					}
				},
				{
					xtype: "button",
					text: "Close",
					iconCls: "pf-navigate_cross",
					handler: function () {

						i_window.close();
					}
				}
			]
		});

		var i_actionBar = i_entityForm.getActionbar();
		i_actionBar.hide();

		i_window.add(i_entityForm);
		i_window.show();
	},

	onClearClick: function () {

		var i_self = this;

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

		return i_self;
	},

	getDisplayFields: function () {

		var i_self = this;
		var a_fields = [];
		var i_model = i_self.getModel();
		var a_columns = i_model.getFields();

		Ext.Array.each(a_columns, function (o_column) {
			if (o_column.isTitle) {
				a_fields.push(o_column.as || o_column.name);
			}
		});

		if (a_fields.length === 0) {
			a_fields.push(i_model.idProperty);
		}

		return a_fields;
	},

	getRenderFn: function () {

		var i_self = this;
		var a_fields = i_self.getDisplayFields();

		var f_renderer = function (v) {

			var s_value = v[i_self.valueField];
			var a_values = [];

			Ext.Array.each(a_fields, function (s_field) {
				if (v[s_field]) {
					a_values.push(ip2.i18n(v[s_field]));
				}
			});

			if (a_values.length > 0) {
				if (a_values.length == 1) {
					s_value = a_values[0];
				}
				else {
					s_value = a_values.join(" - ");
				}
			}

			return s_value;
		};

		return f_renderer;
	},

	getDisplayTemplate: function () {

		var i_self = this;
		return i_self.getRenderTemplate(i_self.getRenderFn());
	},

	getRenderTemplate: function (f_renderer) {

		var i_self = this;

		f_renderer = Ext.isFunction(f_renderer) ? f_renderer : i_self.getRenderFn();

		var i_tpl = Ext.create("Ext.XTemplate",
			"<tpl for=\".\">",
			"<li role=\"option\" class=\"x-boundlist-item\" style=\"text-overflow: ellipsis; white-space: nowrap; overflow:hidden;\">",
			"{[this.renderer(values)]}",
			"</li>",
			"</tpl>",
			{
				renderer: f_renderer
			}
		);

		return i_tpl;
	},

	getTemplate: function () {

		var i_cmp = this;

		var i_tpl = Ext.create("Ext.XTemplate",
			"<tpl for=\".\">",
			"{[typeof values === \"string\" ? values : this.renderer(values)]}",
			"<tpl if=\"xindex < xcount\">" + i_cmp.delimiter + "</tpl>",
			"</tpl>",
			{
				renderer: i_cmp.getRenderFn()
			}
		);
		return i_tpl;
	},

	onTriggerClick: function () {

		var i_self = this;
		if (!i_self.readOnly && !i_self.disabled) {
			if (i_self.isExpanded) {
				i_self.collapse();
			}
			else {
				i_self.allQuery = "";
				delete i_self.lastQuery;
				if (i_self.triggerAction === "all") {
					i_self.doQuery(i_self.allQuery, true);
				}
				else if (i_self.triggerAction === "last") {
					i_self.doQuery(i_self.lastQuery, true);
				}
				else {
					i_self.doQuery(i_self.getRawValue(), false, true);
				}
			}
		}
	},

	onPageChange: function (toolbar, newPage) {

		this.loadPage(newPage, {
			rawQuery: true
		});
		return false;
	},

	setValue: function (value) {

		var i_self = this;
		var a_union = [];

		if (value && Ext.isString(value)) {
			value = value.split(",");
		}

		value = Ext.Array.from(value).filter(function(value) {
			return !Ext.isEmpty(value);
		});

		var a_args = [value];

		i_self.callParent(a_args);

		if (value) {

			a_union = ip2.dmd.unionize(i_self.valueField, value);

			if (i_self.getUnions()) {

				var a_unions = i_self.getUnions() || [];

				Ext.Array.each(a_unions, function (o_template) {
					a_union.push(o_template);
				});
			}

			var o_extraParams = i_self.getExtraParams() || {};

			if (o_extraParams.filter) {

				var a_temp = [];

				if (Ext.isArray(o_extraParams.filter)) {
					a_temp = o_extraParams.filter;
				}
				else if (Ext.isString(o_extraParams.filter)) {

					var a_decoded = Ext.decode(o_extraParams.filter, true);

					a_temp = Ext.Array.from(a_decoded);
				}

				Ext.Array.each(a_temp, function (o_template) {
					a_union.push(o_template);
				});
			}

			var o_customFilter = i_self.getCustomFilter();

			if (o_customFilter) {
				a_union.push(o_customFilter);
			}

			i_self.setUnion(a_union);
		}
		else {
			i_self.setUnion(null);
		}

		return i_self;
	},

	loadNewRecord: function (i_record, f_callback) {

		var i_self = this;

		f_callback = f_callback || Ext.emptyFn;

		Ext.Ajax.request({
			url: "/ip2-services/ip2dmdProxy.aspx",
			params: {
				action: "getRows",
				context: i_self.getContext() || "grid",
				dmdFile: i_self.getDmd(),
				uiName: i_self.getView(),
				model: i_self.getEntity(),
				where: i_record.idProperty + " = " + i_record.get(i_record.idProperty)
			},
			success: function (o_response) {

				var o_result = Ext.decode(o_response.responseText, true) || {
					success: false,
					rows: [{}]
				};

				if (!o_result.rows) {
					o_result.rows = [{}];
				}

				var o_data = o_result.rows[0];

				f_callback(o_data);
			},
			failure: function () {
				f_callback({});
			}
		});
	},

	getGrowWidth: function () {

		var i_self = this;

		var value = i_self.inputEl.dom.value;
		var a_fields;
		var i_store;
		var dataLn;
		var currentLongestLength;
		var i;
		var item;
		var itemLn;

		if (i_self.growToLongestValue) {

			a_fields = i_self.getDisplayFields();
			i_store = i_self.store;
			dataLn = i_store.data.length;
			currentLongestLength = 0;

			for (i = 0; i < dataLn; i++) {

				var a_values = [];

				Ext.Array.each(a_fields, function(s_field){
					var s_value = i_store.getAt(i).data[s_field];
					a_values.push(s_value);
				});

				item = a_values.join(" - ");

				itemLn = item.length;

				if (itemLn > currentLongestLength) {
					currentLongestLength = itemLn;
					value = item;
				}
			}
		}
		return value;
	}
});
