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

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

	alias: [
		"widget.restentitypicker",
		"widget.ux.form.field.restentitycombobox"
	],

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

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

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

	emptyText: ip2.i18n({
		da: "Søg...",
		en: "Search..."
	}),

	lastQuery: "",

	config: {
		dmd: "",
		entity: "",
		model: null,
		allowAdd: false,
		url: "",
		searchUrl: "",
		rootProperty: "rows",
		totalProperty: "totalElements",
		limitParam: "limit",
		proxy: null,
		asObject: false
	},

	initComponent: function () {

		var i_self = this;

		i_self.store = i_self.createStore();

		i_self.callParent(arguments);

		i_self.initDefinitions();

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

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

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

						if (i_self.readOnly) {
							i_self.setIconCls("");
							i_self.getTrigger("clear").hide();
							i_self.getTrigger("new").hide();
						}
						else {
							i_self.getTrigger("new")[i_self.getAllowAdd() ? "show" : "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();
							}
						}
					}
				}
			},
			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" : "");

					if (s_value) {
						i_field.getTrigger("clear")[b_readOnly ? "hide" : "show"]();
					}
					else {
						i_field.getTrigger("clear").hide();
					}

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

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

		return i_self;
	},

	initDefinitions: function () {

		var i_self = this;

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

		var i_model = ip2.model({
			dmd: s_dmd,
			entity: s_entity
		});

		i_self.setModel(i_model);

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

	initValue: function() {

		var i_self = this;
		var value = i_self.value;

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

		var i_model = i_self.getModel();

		var a_loaded = [];

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

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

		if (Ext.isObject(value)) {

			var i_store = i_self.getStore();

			i_self.on({
				afterrender: {
					fn: function(i_field) {

						i_created = i_model.create(value);

						i_self.suspendCheckChange++;
						i_self.setValue(i_created);
						i_self.suspendCheckChange--;
					},
					single: true
				}
			});

			i_self.originalValue = i_self.lastValue = value;
			i_self.resetOriginalValue();
		}
		else {

			var n_load = a_values.length;

			if (n_load) {

				var i_proxy = i_self.getProxy();

				var s_root = i_proxy.getReader().getRootProperty();

				var i_reader = i_proxy.getReader();

				i_reader.setRootProperty("");

				i_model.setProxy(i_proxy);

				Ext.Array.each(a_values, function(n_value) {

					i_created = i_model.create({});
					i_created.set(i_created.idProperty, n_value);

					i_created.load({
						callback: function(i_record, i_operation, b_success) {

							n_load--;

							if (i_record.get(i_record.idProperty)) {
								a_loaded.push(i_record);
							}

							if (n_load === 0) {

								i_reader.setRootProperty(s_root);

								var i_store = i_self.getStore();

								i_store.loadData(a_loaded, true);

								i_self.suspendCheckChange++;
								i_self.setValue(a_values);
								i_self.suspendCheckChange--;
								i_self.originalValue = i_self.lastValue = i_self.getValue();
							}
						}
					});
				});
			}
			else {
				i_self.suspendCheckChange++;
				i_self.setValue(a_values);
				i_self.suspendCheckChange--;
				i_self.originalValue = i_self.lastValue = i_self.getValue();
			}
		}
	},

	getValue: function() {

		var i_self = this;
		var result = i_self.value;

		var i_selection = i_self.getSelectedRecord();

		if (i_selection) {
			if (i_self.getAsObject()) {
				result = i_selection.getData();
			}
		}

		return result;
	},

	createStore: function() {

		var i_self = this;

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

		var i_model = ip2.model({
			dmd: s_dmd,
			entity: s_entity
		});

		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";

		var i_store = Ext.create("Ext.data.Store", {
			model: i_model,
			proxy: i_self.createProxy(),
			pageSize: i_self.pageSize,
			autoLoad: false,
			listeners: {
				beforeload: {
					fn: function(i_store, i_operation) {

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

						var n_page = i_operation.getPage() || 1;

						if (!i_operation.getUrl()) {
							i_operation.setUrl(i_proxy.getUrl());
						}

						n_page--;

						if (n_page <= 0) {
							n_page = 1;
						}

						var o_apply = {};
						o_apply[s_page] = n_page;

						Ext.apply(o_extraParams, o_apply);
					}
				}
			}
		});

		i_self.setModel(i_model);

		return i_store;
	},

	onBindStore: function(i_store, o_initial) {

		var i_self = this;
		i_self.callParent(arguments);

		var i_pickerSelectionModel = i_self.pickerSelectionModel;

		i_pickerSelectionModel.deselectOnContainerClick = false;
	},

	isEqual: function(newVal, oldVal) {

		var i_self = this;
		var b_equal = true;

		var a_new = Ext.Array.from(newVal);
		var a_old = Ext.Array.from(oldVal);

		var n_length = a_new.length;

		if (a_new.length !== a_old.length) {
			b_equal = false;
		}

		if (b_equal) {
			if (i_self.getAsObject()) {

				var s_new = Ext.encode(newVal);
				var s_old = Ext.encode(oldVal);

				b_equal = s_new == s_old;
			}
			else {
				for (var i = 0; i > n_length; i++) {

					if (a_old[i] !== a_new[i]) {
						b_equal = false;
					}
				}
			}
		}

		return b_equal;
	},

	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,
			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 s_entity = i_self.getEntity();
		var s_dmd = i_self.getDmd();

		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: s_dmd,
			entity: s_entity,
			view: "portfolio",
			keys: {},
			action: "new",
			dataParent: i_window,
			transactiontype: s_entity,
			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(i_loaded) {

									var i_store = i_self.getStore();
									i_store.loadData([i_loaded], true);
									i_self.setValue(i_loaded.get(i_loaded.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.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 (o_values) {

			var s_value = null;
			var a_values = [];

			Ext.Array.each(a_fields, function(s_field) {
				if (o_values[s_field]) {
					a_values.push(ip2.i18n(o_values[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_self = this;

		var i_tpl = Ext.create("Ext.XTemplate",
			"<tpl for=\".\">",
				"{[typeof values === \"string\" ? values : this.renderer(values)]}",
				"<tpl if=\"xindex < xcount\">" + i_self.delimiter + "</tpl>",
			"</tpl>",
			{
				renderer: i_self.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;
	},

	loadNewRecord: function(i_record, f_callback) {

		var i_self = this;

		var i_model = i_self.getModel();

		var i_load = i_model.create({});

		i_load.set(i_model.idProperty, i_record.get(i_record.idProperty));

		f_callback = f_callback || Ext.emptyFn;

		i_load.load({
			success: function(i_record, i_operation) {
				f_callback(i_record);
			},
			failure: function() {
				f_callback({});
			}
		});
	},

	createProxy: function() {

		var i_self = this;

		var s_limit = i_self.getLimitParam();

		var i_proxy = Portfolio.util.Handler.getProxyByEntity({
			dmd: i_self.getDmd(),
			entity: i_self.getEntity()
		});

		i_proxy.setLimitParam(s_limit || "limit");

		var i_reader = i_proxy.getReader();

		i_reader.setRootProperty(i_self.getRootProperty() || "rows");
		i_reader.setTotalProperty(i_self.getTotalProperty() || "totalElements")

		i_proxy.on({
			exception: {
				fn: function (i_proxy, i_response, i_operation) {

					var s_type = i_response.responseType;

					Ext.USE_NATIVE_JSON = false;

					var o_result = Ext.decode(i_response.responseText, true);

					//Ext.USE_NATIVE_JSON = true;

					if (s_type == "json") {
						o_result = i_response.responseJson;
					}

					o_result = o_result || {
						stmt: i_response.aborted ? "request aborted" : "",
						message: i_response.aborted ? "request aborted" : ""
					};

					var i_requst = i_operation.getRequest();

					var o_params = i_requst.getParams();
					var s_url = i_requst.getUrl();

					var o_config = {
						statement: o_result.stmt,
						params: o_params,
						url: s_url
					};

					if (Portfolio.util.Message) {
						Portfolio.util.Message.Add("Proxy exception", {
							message: o_result.message,
							params: o_config
						}, "sql");
					}
				}
			}
		});

		if (i_self.getUrl()) {
			i_proxy.setUrl(i_self.getUrl());
		}

		i_self.setProxy(i_proxy);

		return i_proxy;
	},

	setValue: function(value) {

		var i_self = this;

		var a_result = [];

		var i_model = i_self.getModel();

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

		Ext.Array.each(a_values, function(value) {

			var i_result = value;

			if (Ext.isObject(value)) {

				if (!value.isModel) {
					i_result = i_model.create(value);
				}
			}

			a_result.push(i_result);
		});

		i_self.callOverridden(a_result);

		if (Ext.isObject(value)) {

			var i_result = value;

			if (i_result.isModel) {
				i_self.value = i_result.getData();
			}
			else {

				i_result = i_model.create(value);

				i_self.value = i_result.getData();
			}
		}
	},

	getWhere: function () {

		var i_self = this;
		var o_model = i_self.getModel().prototype.dmdModel;
		var a_entities = o_model.entities;
		var s_view = "portfolio";

		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;
	}
});
