Ext.define("Portfolio.entity.view.Grid", {

	extend: "Ext.grid.Panel",

	xtype: "portfolio-entity-grid",

	alias: [
		"widget.entity.grid",
		"widget.ip2pagingGridOld"
	],

	layout: "fit",

	border: false,

	multiColumnSort: true,

	requires: [
		"Portfolio.entity.view.Form",
		"Portfolio.entity.util.Toolbar",
		"Ext.ux.ToolbarDroppable",
		"Ext.ux.file.util.Handler",
		"Ext.ux.grid.filter.util",
		"Ext.ux.grid.filter.Toolbar",
		"Ext.ux.grid.filter.Menu"
	],

	config: {
		providerID: "",
		dmd: "",
		uiName: "portfolio",
		editMode: "tab",
		dmdName: "",
		dmdCfg: null,
		defaultFilter: "",
		defaultCollection: "",
		customFilter: null,
		filterBar: null,
		entityToolBar: null,
		entity: null,
		record: null,
		dropZone: null,
		autoLoad: true,
		filterable: true,
		allowActions: true,
		allowFilterMenu: true,
		allowMenuOnFilters: true,
		allowLink: true,
		allowExport: true,
		allowSearch: true,
		selected: null,
		parentEntity: null,
		parentKeys: null,
		childPanel: null,
		rowMenu: null,
		autoSelect: true,
		remoteSort: true,
		showTotalCount: true,
		useScroller: false,
		searchCombo: true,
		templateConfig: null,
		features: [],
		menuApp: null
		
	},

	listeners: {
		afterrender: {
			fn: function() {

				var i_self = this;
				var s_uiName = i_self.getUiName();

				var o_entity = i_self.getEntity();
				var o_view = o_entity.ui.grids[s_uiName];

				if (o_view.drop) {
					var a_entry = o_view.drop.entities || [];

					if (a_entry.length > 0) {

						var i_dropzone = Ext.create("Ext.ux.grid.DropZone", {
							grid: i_self,
							entity: o_entity,
							dropFn: function(s_value, o_drop) {

								if (s_value) {

									var i_store = i_self.getStore();

									var o_config = Ext.apply({}, {
										dmd: o_drop.dmd,
										entity: o_drop.name,
										entityName: o_drop.name,
										uiName: o_drop.view || "portfolio",
										context: "form"
									});

									var i_model = Portfolio.util.Handler.model(o_config);

									var i_record = i_model.create({});

									i_record.set(o_drop.property, s_value);

									i_self.handleAction(i_record, "create", 0);
								}
							}
						});

						i_self.setDropZone(i_dropzone);
						i_self.add(i_dropzone);
					}
				}

				var a_columns = i_self.getColumnManager().getColumns();

				Ext.Array.each(a_columns, function(i_column) {

					if (i_column.search) {
						i_self.fireEvent("colToSearch", i_self, i_column);
					}
				});


				var i_actionBar = i_self.getEntityToolBar();

				var i_searchfield = i_actionBar.getComponent("search");

				if (o_view.hasOwnProperty("searchable") && !o_view.searchable) {
					if (i_searchfield) {
						i_searchfield[o_view.searchable ? "show" : "hide"]();
					}
                }

				i_self.applyReset();

				i_self.createKeyEvents();
			}
		},
		columnresize: {
			fn: function (container, col, width) {
				var i_self = this;
				i_self.fireEvent("savestate", i_self);
			}
		},
		columnmove: {
			fn: function (container, col, width) {
				var i_self = this;
				i_self.fireEvent("savestate", i_self);
			}
		},
		columnshow: {
			fn: function (container, col, width) {
				var i_self = this;
				i_self.fireEvent("savestate", i_self);
			}
		},
		columnhide: {
			fn: function (container, col, width) {
				var i_self = this;
				i_self.fireEvent("savestate", i_self);
			}
		},
		savestate: {
			fn: function() {
				var i_self = this;
				i_self.saveState();
			},
			buffer: 250
		},
		afterFilter: {
			fn: function(i_filterbar, n_filters) {

				var i_self = this;
				var i_toolbar = i_self.getEntityToolBar();
				i_toolbar.fireEvent("afterfilter", n_filters);
			}
		},
		colToSearch: {
			fn: function (i_panel, i_column) {

				var i_self = this;
				var i_actionBar = i_self.getEntityToolBar();

				var i_searchfield = i_actionBar.getComponent("search");

				if (i_searchfield) {

					var a_fields = i_actionBar.query("field[searchfield=true]");

					var i_found =  Ext.Array.findBy(a_fields, function(i_field) {
						return i_field.dataIndex == i_column.dataIndex;
					});

					if (!i_found) {
						var n_index = i_actionBar.items.indexOf(i_searchfield);
					

						if (a_fields.length > 0) {
							n_index = i_actionBar.items.indexOf(a_fields[a_fields.length - 1]);
						}

						var s_type = "textfield";

						var o_config = {
							emptyText: ip2.i18n(i_column.title),
							dataIndex: i_column.dataIndex,
							searchfield: true,
							isFormfield: false,
							ui: "function-field"
						};

						if (Ext.isObject(i_column.search)) {

							s_type = "combobox";

							var o_search = i_column.search || {};

							var i_model = ip2.model({
								dmd: o_search.dmd,
								view: o_search.view,
								entity: o_search.entity,
								context: "grid"
							});

							var i_store = Ext.create("Ext.data.Store", {
								model: i_model,
								proxy: Portfolio.util.Handler.getProxyByEntity({
									dmd: o_search.dmd,
									view: o_search.view,
									entity: o_search.entity,
									context: "grid"
								}),
								remoteSort: true,
								pageSize: 100
							});

							Ext.apply(o_config, {
								store: i_store,
								displayField: o_search.displayField || "key",
								valueField: o_search.valueField || "value",
								queryParam: "search",
								queryMode: "remote",
								triggerAction: "all",
								editable: false,
								forceSelection: false,
								queryCaching: false,
								minWidth: 180,
								grow: true,
								growToLongestValue: true,
								multiSelect: true,
								listeners: {
									specialkey: {
										fn: function (i_field, i_event) {

											var s_key = i_event.getKey();

											if (s_key == i_event.ENTER) {

												var i_store = i_self.getStore();

												if (i_store.clearAndLoad) {
													i_store.clearAndLoad();
												}
												else {
													i_store.load();
												}
											}
										}
									},
									change: {
										fn: function (i_field, value) {
											var i_store = i_self.getStore();
											i_store.clearAndLoad();
										}
									},
									autosize: {
										fn: function (i_field) {
											var i_picker = i_field.getPicker();
											i_picker.setWidth(i_field.bodyEl.getWidth());
										},
										buffer: 1
									}
								},
								triggers: {
									picker: {
										weight: 1,
										handler: "onTriggerClick",
										scope: "this"
									}
								}
							});
						}
						else {
							Ext.apply(o_config, {
								listeners: {
									specialkey: {
										fn: function (i_field, i_event) {

											var s_key = i_event.getKey();

											if (s_key == i_event.ENTER) {

												var i_store = i_self.getStore();

												if (i_store.clearAndLoad) {
													i_store.clearAndLoad();
												}
												else {
													i_store.load();
												}
											}
										}
									}
								},
							});
						}

						var i_field = Ext.widget(s_type, o_config);

						i_actionBar.add(n_index + 1, [i_field]);
					}
				}
			}
		},
		changeview: {
			fn: function(s_view) {
				
				var i_self = this;

				var s_oldView = i_self.getUiName();

				if (s_oldView != s_view) {

					var o_modelConfig = i_self.getModelConfig();
					var o_entityInfo = i_self.getEntityInfo();

					o_modelConfig.uiName = s_view;
					o_entityInfo.view = s_view;

					i_self.setUiName(s_view);
					i_self.model = null;

					i_self.getModel();

					var i_menuApp = i_self.getMenuApp();

					if (i_menuApp) {

						if (i_menuApp.destroy) {
							i_menuApp.destroy();
						}
					}
					
					i_self.setMenuApp(null);

					i_self.setProviderID([o_modelConfig.dmd, o_modelConfig.entityName, o_modelConfig.uiName, Portfolio.util.Handler.baseconfig.session.preset.origin].join("_"));

					var i_newStore = i_self.createStore();
					var a_columns = i_self.getColumns(i_newStore);
					
					var i_actionBar = i_self.getEntityToolBar();
					i_actionBar.setStore(i_newStore);
					
					i_self.reconfigure(i_newStore, a_columns);
				}
			}
		}
	},

	initComponent: function () {

		var i_self = this;

		delete i_self.view;

		i_self.getEntityInfo();

		var o_config = i_self.getModelConfig();

		i_self.setProviderID([o_config.dmd, o_config.entityName, o_config.uiName, Portfolio.util.Handler.baseconfig.session.preset.origin].join("_"));
		i_self.setDmdName(o_config.dmd.split("/").pop().split(".").shift());

		i_self.createUI();

		i_self.callParent();

		var i_header = i_self.headerCt;

		i_header.on({
			boxready: {
				fn: function(i_item) {
					if (i_self.getFilterable()) {

						var i_toolbar = i_self.getFilterBar();
						var o_entity = i_self.getEntity();

						var s_uiName = i_self.getUiName();

						if (i_toolbar) {

							var s_ddGroup = i_header.reorderer.dragZone.ddGroup;
							i_toolbar.dd.addDDGroup(s_ddGroup);

							var a_filters = o_entity.ui.grids[s_uiName].filters || [];
							var s_defaultFilter = i_self.getDefaultFilter();

							if (!s_defaultFilter && a_filters.length > 0) {
								i_toolbar.loadFilters(a_filters);
							}
						}
					}
				},
				buffer: 100
			}
		});

		i_self.createRowMenu();
		i_self.addDocked(i_self.createToolbars());
		i_self.addHandlers();
		i_self.convertCopyFn();

		i_self.enableBubble("updateTotalCount");

		return i_self;
	},

	convertCopyFn: function() {

		var i_self = this;
		var o_entity = i_self.getEntity();

		i_self.copyFn = i_self.copyFn = i_self.copyFn || o_entity.copyFn;

		var s_copyFn = i_self.copyFn = i_self.copyFn || "";

		if (s_copyFn) {
			var a_split = s_copyFn.split(".");
			var o_current = window;
			var b_found = false;
			Ext.Array.each(a_split, function(s_part) {
				o_current = o_current[s_part];
				if (o_current && Ext.isFunction(o_current)) {
					i_self.copyFn = o_current;
					b_found = true;
					return false;
				}
			});
			if (!b_found) {
				i_self.copyFn = "";
			}
		}
	},

	handleAction: function(i_record, s_action, n_mode) {

		var i_self = this;
		var o_config = i_self.getModelConfig();

		s_action = s_action || "update";
		var s_dmd = i_self.getDmdName();

		o_config.defaultCollection = i_self.getDefaultCollection();

		var o_clone = Ext.clone(o_config);
		delete o_clone.container;

		if (Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.update") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.read") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.copy") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_clone.entityName + ".update") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_clone.entityName + ".read") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_clone.entityName + ".copy")) {

			var o_keys = {};

			if (i_record) {
				o_keys[i_record.idProperty] = i_record.get(i_record.idProperty);
			}

			Ext.apply(o_clone, {
				keys: o_keys
			});

			var i_window = i_self.up("window");

			if (i_self.fireEvent("before" + s_action, i_self, o_clone)) {

				if (i_window) {
					Portfolio.app.fireEvent("entityWindow", o_clone, s_action, null, i_window.zIndexManager.id);
				}
				else {
					var i_form = i_self.up("entityform");

					if (i_form || (i_self.getEditMode() === "window" || n_mode === 1)) {
						Portfolio.app.fireEvent("entityWindow", o_clone, s_action);
					}
					else {
						Portfolio.app.fireEvent("entityedit", o_clone, s_action);
					}
				}
			}

		}
	},

	setupColumns: function(a_columns, i_store) {

		var i_self = this;
		var a_clone = Ext.Array.slice(a_columns);
		var a_return = [];
		var b_diff = false;

		var o_setting = Portfolio.util.Handler.profile.get(i_self.getProviderID() + ".setting", {
			columns: {
				order: [],
				size: []
			}
		});

		Ext.applyIf(o_setting, {
			columns: {
				order: [],
				size: []
			}
		});

		if (Ext.isArray(o_setting)) {
			o_setting = {
				columns: {
					order: [],
					size: []
				}
			};
		}

		if (a_clone.length != o_setting.columns.order.length) {
			b_diff = true;
		}
		else {
			Ext.Array.each(a_clone, function(c_column) {

				var o_found = Ext.Array.findBy(o_setting.columns.order, function(db_column) {
					return c_column.dataIndex == db_column.dataIndex;
				});

				if (!o_found) {
					b_diff = true;
				}
			});
		}

		var n_length = o_setting.columns.order.length;

		o_setting.columns.order = o_setting.columns.order.filter(function(o_column) {
			return o_column.dataIndex;
		});

		if (!b_diff) {
			b_diff = n_length != o_setting.columns.order.length;
		}

		if (o_setting.columns.order.length === 0 || b_diff) {
			a_return = i_self.saveInitialSetting(i_store);
		}
		else {
			Ext.Array.each(o_setting.columns.order, function(o_column) {
				Ext.Array.each(a_clone, function(i_clone) {
					if (o_column.dataIndex == i_clone.dataIndex) {
						if (!i_clone.hide) {
							i_clone.hidden = o_column.hidden || false;
							a_return.push(i_clone);
							return false;
						}
					}
				});
			});
			Ext.Array.each(a_return, function(i_column) {
				if (!i_column.hide) {
					Ext.Array.each(o_setting.columns.size, function(o_size) {
						if (i_column.dataIndex == o_size.dataIndex) {
							if (o_size.width !== undefined) {
								i_column.width = o_size.width;
								i_column.flex = undefined;
								return false;
							}
						}
					});
				}
				delete i_column.hide;
			});
		}
		return a_return;
	},

	addHandlers: function() {

		var i_self = this;
		var i_store = i_self.getStore();
		var o_config = i_self.getModelConfig();

		if (i_self.getAutoLoad()) {
			if (!i_self.getDefaultFilter()) {
				i_store.load({
					params: {
						start: 0
					}
				});
			}
		}

		i_self.mon(Portfolio.util.Handler.App, "entityupdate:" + o_config.entityName, function(i_record, s_action) {

			if (!i_self.destroyed) {
				var a_records = Ext.Array.from(i_record);

				var n_count = a_records.length;

				var i_view = i_self.getView();

				var o_info = i_self.getEntityInfo();

				var o_dmd = o_info.dmd;
				var o_model = o_dmd.model;

				var o_proxy = o_model.proxy;

				o_proxy.portfolio = o_proxy.hasOwnProperty("portfolio") ? o_proxy.portfolio : true;

				if (n_count > 0 && s_action == "update") {

					i_view.setLoading(true);

					Ext.Array.each(a_records, function (i_record) {

						var n_index = i_store.findBy(function (i_search) {
							return i_record.get(i_record.idProperty) == i_search.get(i_record.idProperty);
						});

						if (n_index > -1) {

							var i_viewRecord = i_store.getAt(n_index);

							if (o_proxy.portfolio) {
								i_self.getUpdatedRecord(i_record, function (o_data) {

									i_store = i_self.getStore();

									if (i_store) {
										i_viewRecord.set(o_data);
										i_viewRecord.commit(true);
										n_count--;

										if (n_count === 0) {

											i_store.fireEvent("datachanged", i_store);
											i_store.fireEvent("refresh", i_store);

											i_view.refreshNode(i_viewRecord);
											i_view.setLoading(false);
										}
									}
								});
							}
							else {

								var i_storeProxy = i_store.getProxy();
								var i_recordProxy = i_viewRecord.getProxy();

								i_viewRecord.self.setProxy(i_storeProxy);

								i_viewRecord.load({
									success: function(i_loaded, i_operation) {
										i_viewRecord.set(i_loaded.getData());

										i_viewRecord.commit(true);
										i_view.refreshNode(i_viewRecord);
										n_count--;

										if (n_count === 0) {
											i_view.setLoading(false);
										}

										i_viewRecord.self.setProxy(i_recordProxy);
									},
									failure: function(err) {
										n_count--;

										if (n_count === 0) {
											i_view.setLoading(false);
										}

										i_viewRecord.self.setProxy(i_recordProxy);
									}
								});
							}
						}
						else {
							n_count--;
							if (n_count === 0) {
								i_view.setLoading(false);
							}
						}
					});
				}
				else {
					i_store.load();
				}
			}

			
		});
	},

	createStore: function() {

		var i_self = this;
		var b_autoLoad = i_self.getAutoLoad();
		var i_model = i_self.getModel();
		var a_sorters;
		var s_uiName = i_self.getUiName();

		var o_entity = i_self.getEntity();
		var o_info = i_self.getEntityInfo();

		if (o_info.view.sort) {

			a_sorters = Ext.Array.map(o_info.view.sort.split(","), function (s_value) {
				var s = Ext.Array.filter(s_value.split(" "), Boolean);
				return {
					property: s[0],
					direction: s[1] ? s[1] : "ASC"
				};
			});
		}

		if (o_info.view.hasOwnProperty("remoteSort")) {
			i_self.setRemoteSort(o_info.view.remoteSort);
		}

		if (i_self.getDefaultFilter()) {
			b_autoLoad = false;
		}

		var a_features = i_self.getFeatures();

		var a_extFeatures = Ext.Array.from(o_info.view.extfeatures);

		a_features = a_features.concat(i_self.createFeatures(a_extFeatures));

		var b_buffered = a_features.length > 0 ? false : true;

		var s_storeType = b_buffered ? "Ext.data.BufferedStore" : "Ext.data.Store";

		var i_store = Ext.create(s_storeType, {
			model: i_model,
			proxy: Portfolio.util.Handler.getProxyByEntity(i_self.getModelConfig()),
			remoteSort: i_self.getRemoteSort(),
			autoSync: false,
			sorters: a_sorters,
			ops: [],
			first: true,
			pageSize: o_info.view.pageSize || 100,
			purgePageCount: o_info.view.hasOwnProperty("purgePageCount") ? o_info.view.purgePageCount : 0,
			prevSearch: "",
			autoLoad: b_autoLoad,
			listeners: {
				beforeload: {
					fn: function (i_store, i_operation) {

						var i_proxy = i_store.getProxy();
						var o_sorters = i_store.getSorters();
						var o_extraParams = i_proxy.getExtraParams();
						var a_sort = [];
						var a_where = [];
						var s_sort = "";

						delete o_extraParams.where;

						a_where = a_where.filter(function(s_value) {
							return s_value;
						});

						var i_toolbar = i_self.getToolbar();
						var i_filterbar = i_self.getFilterBar();

						var i_columnManager = i_self.getColumnManager();

						var i_search;

						if (i_toolbar) {
							i_search = i_toolbar.down("#search");
						}

						Ext.Array.each(o_sorters.items, function(o_sort) {

							var i_header = i_columnManager.getHeaderByDataIndex(o_sort.getProperty());

							if (i_header) {
								var s_sorter = (i_header.mapping ? i_header.mapping : o_sort.getProperty()) + " " + o_sort.getDirection();
								a_sort.push(s_sorter);
							}
						});

						var i_grouper = i_store.getGrouper();

						if (i_grouper) {
							i_proxy.setGroupParam("");
							a_sort.unshift(i_grouper.getProperty() + " " + i_grouper.getDirection());
							delete o_extraParams.group;
						}
						else {
							i_proxy.setGroupParam("group");
						}

						if (a_sort.length > 0) {
							i_proxy.setSortParam("");
						}
						else {
							i_proxy.setGroupParam("sort");
						}

						s_sort = a_sort.join(", ");

						if (o_entity.language) {
							var i_pickerLocal = i_self.getToolbar().down("#button-language");
							if (i_pickerLocal) {
								o_extraParams.language = i_pickerLocal.key;
								o_extraParams.languageColumn = o_entity.language.column;
							}
						}

						if (i_filterbar) {
							var s_filterWhere = i_filterbar.getWhere();
							if (s_filterWhere) {
								a_where.push(s_filterWhere);
							}
						}
						if (i_search) {
							o_extraParams.search = i_search.getRawValue();
							if (i_search.getWhere()) {
								var s_searchWhere = i_search.getWhere();
								a_where.push(s_searchWhere);
								o_extraParams.search = "";
							}
						}

						if (i_self.extraParams) {
							var o_extra = i_self.extraParams || {};
							if (o_extra.hasOwnProperty("where")) {
								var s_extraWhere = o_extra.where;
								a_where.push(s_extraWhere);
							}
							Ext.apply(o_extraParams, o_extra);
						}
						else {
							delete o_extraParams.filter;
						}

						if (s_sort) {
							Ext.apply(o_extraParams, {
								sort: s_sort,
							});
						}

						var a_searchfields = i_toolbar.query("field[searchfield=true]");

						var i_template = new Ext.XTemplate(
							"{dataIndex} {[this.getStatement(values.value)]}",
							{
								getStatement: function (values) {

									var a_result = [];
									var n_length = values.length;

									Ext.Array.each(values, function (s_value) {
										if (s_value) {

											var s_result = "";

											if (n_length == 1) {
												s_result = "'%" + s_value.trim() + "%'";
											}
											else {
												s_result = "'" + s_value.trim() + "'";
											}

											a_result.push(s_result);
										}
									});

									var s_statement = n_length > 1 ?
										" IN " + "(" + a_result.join(", ") + ")" : "like " + a_result.join("");

									return s_statement;
								}
							}
						);

						Ext.Array.each(a_searchfields, function (i_field) {

							var s_dataIndex = i_field.dataIndex;
							var value = i_field.getValue();

							var a_values = Ext.Array.from(value).filter(function (value) {
								return value;
							});

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

							if (a_values.length > 0) {
								a_where.push(i_template.apply({
									dataIndex: s_dataIndex,
									value: a_values
								}));
							}
						});

						if (a_where.length > 0) {
							Ext.apply(o_extraParams, {
								where: a_where.join(" AND ")
							});
						}

						if (i_self.getUseScroller()) {
							Ext.apply(o_extraParams, {
								scroll: i_self.getUseScroller()
							});
						}

						Ext.apply(o_extraParams, {
							action: "getRows",
							dir: ""
						});
					}
				},
				load: {
					fn: function (i_store, a_records) {

						var i_proxy = i_store.getProxy();
						var o_extraParams = i_proxy.getExtraParams();
						var i_view = i_self.getView();

						var i_selected = i_self.getSelected();

						a_records = a_records || [];

						var i_optionsColumns = i_self.getColumnManager().getHeaderByDataIndex("options");

						if (i_optionsColumns) {
							i_optionsColumns.setText(i_store.getTotalCount());
						}

						if (!i_self.getAutoSelect()) {
							return;
						}

						if (a_records.length) {

							if (i_selected) {

								var b_found = false;

								Ext.Array.each(a_records, function(i_record) {
									if (i_record.get(i_record.idProperty) == i_selected.get(i_selected.idProperty)) {
										b_found = true;
										i_self.setSelected(i_record);
										i_view.select(i_record, true);
										return false;
									}
								});

								if (!b_found) {
									i_self.setSelected(null);
								}
							}
							else {
								if (a_records.length > 0) {
									i_selected = a_records[0];
									i_self.setSelected(i_selected);
									i_view.select(i_selected, false);
								}
							}
						}
					}
				}

			},
			setNewRecordId: Ext.emptyFn
		});

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

		Ext.apply(o_extraParams, {
			dmdFile: i_model.dmdFile,
			uiName: s_uiName,
			context: "grid",
			action: "getRows"
		});

		var o_view = o_entity.ui.grids[s_uiName];

		if (o_view) {

			o_extraParams = Ext.Object.mergeIf(o_extraParams, o_view.extraParams, {
				filter: []
			});

			if (o_extraParams.filter) {
				if (i_self.getCustomFilter()) {
					var value = i_self.getCustomFilter();
					if (Ext.isObject(value)) {
						if (!Ext.Object.isEmpty(value)) {
							o_extraParams.filter.push(i_self.getCustomFilter());
						}
					}
					else if (Ext.isArray(value)) {
						o_extraParams.filter = o_extraParams.filter.concat(value);
					}
					else {
						delete o_extraParams.filter;
					}
				}
				else {
					delete o_extraParams.filter;
				}
			}

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

		if (i_self.getChildPanel()) {
			o_extraParams.parentEntity = i_self.getParentEntity();
			o_extraParams.parentKeys = i_self.getParentKeys();
		}

		return i_store;
	},

	createTemplateStore: function() {

		var i_self = this;
		var b_autoLoad = i_self.getAutoLoad();
		var i_model = i_self.getModel();

		var i_proxy = ip2.getProxyByEntity(i_self.getModelConfig());

		i_proxy.setActionMethods({
			read: "POST"
		});

		i_proxy.setParamsAsJson(true);

		i_proxy.setExtraParams({});

		

		i_proxy.extractResponseData = function(i_response) {

			var i_proxy = this;
			var i_reader = i_proxy.getReader();

			var o_data = i_response.responseJson || Ext.decode(i_response.responseText, true);

			var o_result = {};

			o_result[i_reader.getRootProperty()] = [];
			o_result[i_reader.getTotalProperty()] = 0;

			if (Ext.isArray(o_data.batch)) {
				o_result = o_data.batch[0];
			}

			return o_result;
		};

		var i_store = Ext.create("Ext.data.Store", {
			model: i_model,
			proxy: i_proxy,
			remoteSort: i_self.getRemoteSort(),
			autoSync: false,
			ops: [],
			first: true,
			pageSize: 100,
			prevSearch: "",
			autoLoad: b_autoLoad,
			listeners: {
				load: {
					fn: function (i_store, a_records) {

						var i_view = i_self.getView();
						var i_selected = i_self.getSelected();

						if (!i_self.getAutoSelect()) {
							return;
						}

						if (a_records.length > 0) {

							if (i_selected) {

								var b_found = false;

								Ext.Array.each(a_records, function(i_record) {

									if (i_record.get(i_record.idProperty) == i_selected.get(i_selected.idProperty)) {
										b_found = true;
										i_self.setSelected(i_record);
										i_view.select(i_record, true);
										return false;
									}
								});

								if (!b_found) {
									i_self.setSelected(null);
								}
							}
							else {
								i_selected = a_records[0];
								i_self.setSelected(i_selected);
								i_view.select(i_selected, false);
							}
						}
					}
				}
			}
		});

		i_self.store = i_store;

		return i_store;
	},

	createUI: function() {

		var i_self = this;
		var o_entity = i_self.getEntity();
		var o_templateConfig = i_self.getTemplateConfig();
		var o_view = o_entity.ui.grids[i_self.getUiName()];
		var b_editable = o_view.editable || false;
		var i_store = o_templateConfig ? i_self.createTemplateStore() : i_self.createStore();
		var a_columns = i_self.getColumns(i_store);
		var o_sorters = i_store.getSorters();
		o_sorters.setMultiSortLimit(a_columns.length - 1);

		if (o_sorters.$sortable) {
			o_sorters.$sortable.setMultiSortLimit(a_columns.length - 1);
		}

		var a_plugins = Ext.Array.from(i_self.plugins);
		var a_viewPlugins = Ext.Array.from(o_view.plugins);
		a_viewPlugins = a_viewPlugins.concat(Ext.Array.from(o_view.gridplugins));

		a_plugins = a_plugins.concat(a_viewPlugins);

		var a_features = i_self.getFeatures();

		var a_extFeatures = Ext.Array.from(o_view.extfeatures);

		a_features = a_features.concat(i_self.createFeatures(a_extFeatures));

		var i_plugin = Ext.create("Ext.grid.plugin.CellEditing", {
			pluginId: "celledit",
			clicksToEdit: 1,
			listeners: {
				beforeedit: {
					fn: function(i_editor, i_context) {

						return b_editable;
					}
				},
				edit: {
					fn: function(i_editor) {

						var i_context = i_editor.context;
						var i_grid = i_context.grid;
						var i_record = i_context.record;
						var i_store = i_grid.getStore();
						var i_proxy = i_store.getProxy();
						var i_view = i_grid.getView();

						var o_info = i_self.getEntityInfo();
						var o_dmd = o_info.dmd;
						var o_model = o_dmd.model;

						var o_proxy = o_model.proxy;

						o_proxy.portfolio = o_proxy.hasOwnProperty("portfolio") ? o_proxy.portfolio : true;

						if (o_proxy.portfolio) {

							if (i_context) {

								var i_column = i_context.column;
								var o_initialConfig = i_column.initialConfig;

								var o_editor = o_initialConfig.editor;

								if (i_record) {

									i_self.getFormRecord(i_record, function(i_formRecord) {

										var s_property = o_editor.map2 || i_context.field;

										i_formRecord.set(s_property, i_context.value);

										i_self.upsertRecord(i_formRecord, function() {

											i_self.getUpdatedRecord(i_record, function(o_data) {
												
												i_store = i_self.getStore();
												if (i_store) {
													i_store.fireEvent("datachanged", i_store);
													i_store.fireEvent("refresh", i_store);

													i_record.set(o_data);
													i_record.commit(true);
													
													i_view.refreshNode(i_record);
												}
											});
										});
									});
								}
							}
						}
						else {

							i_view.refresh();

							i_record.self.setProxy(i_proxy);

							i_record.save({
								callback: function(i_result, i_operation, b_success) {

									var a_message = [];

									if (!b_success) {

										var i_error = i_operation.getError();

										var i_response = i_error.response;

										var o_result = Ext.decode(i_response.responseText, true) || {
											message: ""
										};

										if (o_result.message) {
											a_message.push(o_result.message);
										}
									}

									i_record.self.setProxy(i_proxy);

									if (a_message.length > 0) {

										var s_msg = a_message.join("<br>");

										Portfolio.util.Handler.messageBox({
											icon: Ext.MessageBox.ERROR,
											title: ip2.i18n({
												da: "Fejl",
												en: "Error"
											}),
											closable: true,
											message: ip2.i18n({
												da: "Der skete en fejl under processen:</br> <strong>" + s_msg + "</strong>",
												en: "An error occurred durring the process:</br> <strong>" + s_msg + "</strong>"
											}),
											yesText: ip2.i18n({
												da: "Ok",
												en: "OK"
											})
										});
									}
								}
							});
						}
					}
				}
			}
		});

		i_plugin.getEditor = (function(f_old) {
			return function() {

				var args = [].slice.call(arguments);

				var i_editor = f_old.apply(this, args);

				var i_field = i_editor.field;

				if (i_field.xtype === "isotimestampfield") {
					i_editor.alignment = "tl";
				}

				if (i_field.xtype == "combobox" || i_field.xtype == "entitypicker" || i_field.xtype == "uploadpicker") {

					i_editor.onFocusLeave = (function(f_old) {
						return function() {
							var i_editor = this;
							var i_field = i_editor.field;
							if (!i_field.isExpanded && !i_field.isUploading && !i_field.isHandling) {
								f_old.apply(this, arguments);
							}
						};
					})(i_editor.onFocusLeave);

					i_field.on({
						focus: {
							fn: function(i_field) {
								i_field.expand();
							}
						}
					});
				}

				if (i_field.xtype === "i18ntextfield" || i_field.xtype === "i18nhooktextfield") {
					i_editor.alignment = "tl";
					if (!i_editor.isChanged) {
						i_editor.isChanged = true;
						i_editor.onFocusLeave = (function(f_old) {
							return function(e) {
								var i_self = this;
								var i_field = this.field;
								if (!i_field.isChanging) {
									f_old.apply(this, arguments);
								}
							};
						})(i_editor.onFocusLeave);
					}
				}

				return i_editor;
			};
		})(i_plugin.getEditor);

		a_plugins.push(i_plugin);

		var i_selectionModel = i_self.selModel;

		if (!i_selectionModel) {

			i_selectionModel = Ext.apply({}, {
				type: o_view.rowmodel || "rowmodel",
				mode: o_view.mode || "MULTI",
				enableKeyNav: true,
				pruneRemoved: false
			});
		}

		Ext.Object.merge(i_self, {
			store: i_store,
			columns: i_self.setupColumns(a_columns, i_store),
			rowHeight: i_self.rowHeight,
			selModel: i_selectionModel,
			plugins: a_plugins,
			features: a_features,
			numFromEdge: 4,
			listeners: {
				destroy: {
					fn: function () {
						if (i_self.getRowMenu()) {
							i_self.getRowMenu().destroy();
						}
					}
				},
				itemdblclick: {
					fn: function (i_view, i_record, i_item, n_index, i_event, o_options) {

						i_self.handleAction(i_record, "update", 0);
					}
				},
				sortchange: {
					fn: function(i_header, i_column, s_direction) {
						if (i_self.getFilterBar()) {
							i_self.getFilterBar().sortChange(i_column);
						}
					}
				},
				select: {
					fn: function (i_view, i_record) {

						i_self.setSelected(i_record);

						var a_selected = i_self.getSelectionModel().getSelection();

						var i_toolbar = i_self.getEntityToolBar();

						i_toolbar.fireEvent("rowselect", i_toolbar, a_selected);

					}
				},
				selectionchange: {
					fn: function (i_view, i_selected) {

						if (i_selected) {

							var a_records = [];

							if (Ext.isFunction(i_selected.getRecords)) {

								a_records = i_selected.getRecords();

								i_self.setSelected(a_records[0]);
							}
							else {

								var i_record = i_selected.startCell ? i_selected.startCell.record : false;

								if (i_record) {
									a_records = [
										i_record
									];
								}
								
							}
							i_self.fireEvent(a_records.length ? "select" : "deselect", i_view, a_records[0]);
						}
					}
				},
				deselect: {
					fn: function() {
						var a_selected = i_self.getSelectionModel().getSelection();

						var i_toolbar = i_self.getEntityToolBar();

						i_toolbar.fireEvent("rowdeselect", i_toolbar, a_selected);
					}
				},
				itemcontextmenu: {
					fn: function (i_view, i_record, i_html, n_index, i_event) {

						var i_rowMenu = i_self.getRowMenu();
						var i_selModel = i_self.getSelectionModel();

						i_event.stopEvent();

						i_self.setRecord(i_record);

						var a_coords = i_event.getXY();

						if (!i_selModel.isSelected(n_index)) {
							i_view.select(n_index);
						}
						
						if (i_rowMenu) {

							i_rowMenu.fireEvent("beforeaction", i_rowMenu);

							var i_delete = i_rowMenu.down("#itmDelete");
							var n_status = i_record.get("BCKSTS");

							if (n_status) {
								if (n_status == 1900) {
									i_delete.setDisabled(false);
								}
								else {
									i_delete.setDisabled(true);
								}
							}

							if (o_view.features && o_view.features.menu && o_view.features.menu.src) {

								var o_menu = ip2.getEvaled({
									url: o_view.features.menu.src
								});

								if (o_menu) {

									var i_selectionModel = i_self.getSelectionModel();

									var a_records = i_selectionModel.getSelection();

									var o_config = {
										records: a_records,
										parentId: i_self.getId(),
										grid: i_self
									};

									var a_items = o_menu.onInitialize(i_rowMenu, o_config, "grid");

									Ext.Array.each(a_items, function(i_item) {

										var i_menuItm = i_rowMenu.down("#" + i_item.itemId);

										if (i_menuItm) {
											i_rowMenu.remove(i_menuItm);
										}
									});

									i_rowMenu.add(a_items);
								}
							}

							var a_items = i_rowMenu.items.getRange();

							if (a_items.length >  0) {
								i_rowMenu.showAt([a_coords[0], a_coords[1]]);
							}
						}
					}
				}
			},
			viewConfig: {
				trackOver: true,
				loadMask: true,
				variableRowHeight: false
			}
		});
	},

	getColumns: function(i_store) {

		var i_self = this;
		var o_entity = i_self.getEntity();
		i_store = i_store || i_self.getStore();
		var i_proxy = i_store.getProxy();

		var i_model = i_proxy.getModel();

		var s_dmd = i_self.getDmdName();

		var b_allowMenu = (Portfolio.util.Handler.isAccessible("app." + s_dmd + ".functions.columns.menu") ||
							Portfolio.util.Handler.isAccessible("app." + s_dmd + ".functions." + o_entity.name + ".columns.menu"));
		var b_draggable = (Portfolio.util.Handler.isAccessible("app." + s_dmd + ".functions.columns.arrange") ||
							Portfolio.util.Handler.isAccessible("app." + s_dmd + ".functions." + o_entity.name + ".columns.arrange"));

		var b_sortable = true;

		// Get the definitions we need to build the columns array for the grid

		var o_view = o_entity.ui.grids[i_self.getUiName()];
		var o_fields = o_entity.columns;

		var a_columns = o_view.columns || [];
		var a_extraColumns = Ext.Array.from(o_view.extraColumns);

		a_columns = a_columns.concat(a_extraColumns);

		a_columns.sort(function(a, b) {
			var n_a = (Ext.isNumber(a.sequence) ? a.sequence : 0);
			var n_b = (Ext.isNumber(b.sequence) ? b.sequence : 0);

			return n_a - n_b;
		});

		var a_fields = i_model.getFields();
		var a_return = [];

		var o_uitypes = Portfolio.util.Handler.getUitypes();

		var a_entityColumns = [];

		if (Ext.isObject(o_fields)) {
			Ext.Object.each(o_fields, function(s_key, o_value) {
				var o_temp = Ext.apply({
					name: s_key
				}, o_value);
				a_entityColumns.push(o_temp);
			});
		}
		else {
			Ext.Array.each(o_fields, function(o_value) {
				a_entityColumns.push(o_value);
			});
		}

		if (o_view.hasOwnProperty("sortable")) {
			b_sortable = o_view.sortable;
		}

		a_columns = Ext.Array.filter(a_columns, function(o_column) {
			return !o_column.hide;
		});

		Ext.Array.each(a_columns, function(o_uiColumn) {

			var o_column = Ext.apply({
				flex: 1
			}, o_uiColumn);

			var s_name = o_column.name;

			var o_field = {
				column: {}
			};


			o_field = Ext.Array.findBy(a_fields, function(o_value) {
				return o_value.name == o_column.name;
			});

			if (o_uiColumn.width) {
				delete o_column.flex;
			}

			Ext.applyIf(o_column, o_field.column);

			// Translate the column header
			if (o_column.header) {
				if (Ext.isObject(o_column.header)) {
					o_column.header = Portfolio.util.Handler.i18n(o_column.header);
				}
				else {
					o_column.header = Portfolio.util.Handler.dmdTranslate(i_model.prototype, o_column.header);
				}
			}

			if (o_column.title) {
				o_column.header = ip2.i18n(o_column.title, o_column.header);
			}

			// remove editor if we dont have it in our base column
			if (!o_uiColumn.hasOwnProperty("editor")) {
				delete o_column.editor;
			}

			var o_entityColumn = Ext.Array.findBy(a_entityColumns, function(o_value) {
				return o_value.name == o_column.name;
			});

			Ext.applyIf(o_column, o_entityColumn);

			if (o_column.from && !Ext.String.startsWith(o_column.from, "(")) {
				o_column.mapping = o_column.as || o_column.from + "_" + o_column.name;
			}

			var o_xpdInfo = Portfolio.util.Handler.getFieldXpdInfo(o_column.name, o_entity, o_column);

			if (o_xpdInfo) {
				Portfolio.util.Handler.applyFieldXpdInfo(o_column, o_xpdInfo);
			}

			if (o_column.uitype) {

				var o_uitype = o_uitypes[o_column.uitype];

				if (o_uitype && o_uitype.grid) {
					Ext.apply(o_column, o_uitype.grid || {});
				}
			}

			if (o_column.mapping) {
				Ext.applyIf(o_column, {
					draggable: b_draggable,
					menuDisabled: !b_allowMenu,
					sortable:  b_sortable,
					filterable: true
				});
			}
			else {
				Ext.apply(o_column, {
					draggable: b_draggable,
					menuDisabled: !b_allowMenu,
					sortable: b_sortable
				});
			}

			if (o_column.hasOwnProperty("showned")) {
				o_column.hidden = !o_column.showned;
			}

			o_column.dataIndex = o_column.as || s_name;

			a_return.push(o_column);
		});

		if (!i_self.columnsConfig) {
			i_self.columnsConfig = a_return;
		}

		Ext.Array.each(a_return, function(o_config) {

			if (o_config.summaryType == "percentage") {
				Ext.apply(o_config, {
					summaryRenderer: function(value, o_summaryValues, s_field, o_metaData) {

						var n_percentage = 0;

						var i_record = o_metaData.record;

						var i_model = i_store.getModel();

						var i_field = i_model.getField(s_field);

						var o_config = i_field.summary;

						if (o_config.sumField && o_config.devideField) {

							var n_sum = i_record.get(o_config.sumField);
							var n_devide = i_record.get(o_config.devideField);

							n_percentage = ((n_devide / n_sum) * 100);

							if (isNaN(n_percentage)) {
								n_percentage = 0;
							}
							else {
								n_percentage = n_percentage.toFixed(1);
							}

							value = n_percentage + " %";
						}

						return value;
					}
				});
			}

			Ext.apply(o_config, {
				listeners: {
					afterrender: {
						fn: function (i_column) {

							Ext.create("Ext.tip.ToolTip", {
								target: i_column.getEl(),
								html: ip2.i18n(i_column.header),
								anchor: true,
								defealtAlign: "b50-t50",
								listeners: {
									beforeshow: {
										fn: function (i_tip) {

											var o_initialConfig = i_column.initialConfig;

											var s_value = ip2.i18n(o_initialConfig.header);
											i_tip.update(s_value);
										}
									}
								}
							});
						}
					}
				}
			});

			delete o_config.hide;
		});

		a_return.push({
			xtype: "actioncolumn",
			align: "center",
			dataIndex: "options",
			menuDisabled: true,
			hideable: false,
			sortable: false,
			groupable: false,
			text: "0",
			defaults: {
				margin: "auto"
			},
			items: [
				{
					xtype: "button",
					iconCls: "pf-options",
					tooltip: ip2.i18n({
						da: "Mere",
						en: "More"
					}),
					width: 20,
					ui: "function-action",
					isActionDisabled: function(i_column, n_row, n_col, i_action) {
						var o_events = i_self.events || {
							itemcontextmenu: {}
						};

						var a_listeners = Ext.Array.from(o_events.itemcontextmenu.listeners);
						var b_disabled = a_listeners.length === 0;

						if (b_disabled) {

							if (Ext.isFunction(i_action.hide)) {
								i_action.hide();
							}
							else {
								i_action.hidden = true;
							}
						}

						return false;
					},
					handler: function (i_grid, n_row, n_column, i_item, i_event, i_record, i_row) {

						var o_events = i_self.events || {
							itemcontextmenu: {}
						};

						var a_listeners = Ext.Array.from(o_events.itemcontextmenu.listeners);

						if (!Ext.isEmpty(a_listeners)) {

							var i_view = i_self.view;
							i_view.select(i_record);

							Ext.Array.each(a_listeners, function(i_listener) {
								i_listener.fn.call(i_self, i_view, i_record, i_row, n_row, i_event);
							});
						}
					}
				}
			]
		});


		return a_return;
	},

	createRowMenu: function() {

		var i_self = this;

		var i_menu = Ext.create("Ext.menu.Menu", {
			allowOtherMenus: false,
			items: [],
			plain: true,
			listeners: {
				beforeaction: {
					fn: function(i_menu) {

						var i_menuApp = i_self.getMenuApp();
						var a_items = i_self.getRowMenuItems();
						var s_view = i_self.getUiName();

						var o_entityInfo = i_self.getEntityInfo();
						var o_entity = o_entityInfo.entity;
						var o_ui = o_entity.ui;
						var o_grids = o_ui.grids;
						var o_view = o_grids[s_view];
						var o_menu = o_view.menu || {};
						var s_event = "";

						var i_selected = i_self.getSelection()[0]; 

						if (!i_menuApp) {
							
							if (!Ext.Object.isEmpty(o_menu) && o_menu.main) {

								var s_main = o_menu.main;
								var o_path = o_menu.path || {};

								if (!Ext.Object.isEmpty(o_path)) {
									
									Ext.Loader.setConfig({
										paths: o_path
									});
								}

								i_menuApp = Ext.create(s_main, {});

								i_self.setMenuApp(i_menuApp);

								s_event = o_menu.event || "beforemenu";
								i_menuApp.fireEvent(s_event, i_menuApp, i_selected, a_items, i_self);
							}
						}
						else {
							
							s_event = o_menu.event || "beforemenu";
							i_menuApp.fireEvent(s_event, i_menuApp, i_selected, a_items, i_self);
						}

						i_menu.removeAll(true);

						i_menu.add(a_items);

					}
				}
			}
		});

		i_self.setRowMenu(i_menu);
	},

	getRowMenuItems: function() {

		var i_self = this;
		var o_entity = i_self.getEntity();
		var i_selectionModel = i_self.getSelectionModel();
		var s_dmd = i_self.getDmdName();

		var a_items = [];

		if (Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.update") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.read") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_entity.name + ".update") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_entity.name + ".read")) {

			var i_edit = Ext.widget("menuitem", {
				itemId: "item-edit",
				text: Portfolio.util.Handler.i18n({
					da: "Rediger",
					en: "Edit"
				}),
				handler: function (view, record, item, index, e) {
					var a_records = i_selectionModel.getSelection();
					var i_record = a_records[0];
					i_self.handleAction(i_record, "update", 0);
				}
			});

			a_items.push(i_edit);
		}

		if (Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.delete") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_entity.name + ".delete")) {

			var i_delete = Ext.widget("menuitem", {
				text: Portfolio.util.Handler.i18n({
					da: "Slet",
					en: "Delete"
				}),
				itemId: "itmDelete",
				handler: function () {
					var records = i_selectionModel.getSelection();
					i_self.deleteRow(records);
				}
			});
			a_items.push(i_delete);
		}

		if (Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.copy") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_entity.name + ".copy")) {

			var i_copy = Ext.widget("menuitem", {
				text: Portfolio.util.Handler.i18n({
					da: "Kopier",
					en: "Copy"
				}),
				itemId: "itmCopy",
				handler: function () {
					var a_records = i_selectionModel.getSelection();
					var i_record = a_records[0];
					if (i_self.copyFn) {
						i_self.setLoading(Portfolio.util.Handler.i18n({
							da: "Kopier data...",
							en: "Copying data..."
						}));
						i_self.copyFn(i_record, function() {
							i_self.setLoading(false);
							var i_store = i_self.getStore();
							i_store.load();
						});
					}
					else {
						i_self.handleAction(i_record, "copy", 0);
					}
				}
			});
			a_items.push(i_copy);
		}

		return a_items;
	},

	getModel: function() {

		var i_self = this;
		var i_model;
		if (!i_self.model) {
			var o_config = i_self.getModelConfig();
			i_model = Portfolio.util.Handler.model(o_config);
			i_self.model = i_model;
		}
		else {
			i_model = i_self.model;
		}

		return i_model;
	},

	getModelConfig: function() {

		var i_self = this;
		var o_config = i_self.getDmdCfg();

		if (!o_config) {

			o_config = Ext.apply({}, {
				dmd: i_self.getDmd().path,
				entityName: i_self.getDmd().entity || i_self.getDmd().entityName,
				context: "grid",
				uiName: i_self.getUiName()
			});

			i_self.setDmdCfg(o_config);

			if (Ext.isObject(i_self.dmd)) {
				i_self.setDmd(i_self.getDmd().path);
				delete i_self.dmd;
			}
		}

		return o_config;
	},

	getEntityInfo: function() {

		var i_self = this;
		var o_entity;
		var o_entityInfo = i_self.entityInfo;

		if (!o_entityInfo) {

			var o_modelConfig = i_self.getModelConfig();

			var o_config = Portfolio.util.Handler.dmd.getInfo({
				dmd: o_modelConfig.dmd,
				entity: o_modelConfig.entityName,
				view: i_self.getUiName(),
				context: "grid"
			});

			o_entityInfo = o_config;
			o_entity = o_config.entity;
			i_self.entityInfo = o_entityInfo;

			var o_view = o_config.view;

			i_self.setEditMode(o_view.editMode || "tab");

			i_self.setEntity(o_entity);
		}

		return o_entityInfo;
	},

	getToolbar: function() {

		var i_self = this;
		var i_toolbar = i_self.getEntityToolBar();
		return i_toolbar;
	},

	createToolbar: function() {

		var i_self = this;
		var i_model = i_self.getModel();
		var i_store = i_self.getStore();
		var o_config = i_self.getModelConfig();
		var o_entityInfo = i_self.getEntityInfo();
		var s_dmd = i_self.getDmdName();
		var o_entity = i_self.getEntity();

		var o_view = o_entity.ui.grids[i_self.getUiName()];
		var s_searchType = o_view.searchtype ? o_view.searchtype : "";

		var b_allowNew = (
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.create") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_entity.name + ".create")
		);

		var b_allowExport = (
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data.export") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".data." + o_entity.name + ".export")
		);

		if (b_allowExport) {
			b_allowExport = i_self.getAllowExport();
		}

		var b_search = i_self.getSearchCombo();

		if (s_searchType) {
			b_search = s_searchType == "combo";
		}

		var i_toolbar = Ext.widget("entitytoolbar", {
			model: i_model,
			dmdInfo: o_config,
			store: i_store,
			grid: i_self,
			itemId: "maintoolbar",
			dock: "top",
			customFilter: i_self.getCustomFilter(),
			addMode: "form",
			allowNew: b_allowNew,
			allowSearch: i_self.getAllowSearch(),
			allowExport: b_allowExport,
			allowLink: i_self.getAllowLink(),
			searchCombo: b_search,
			entityInfo: o_entityInfo
		});

		i_self.setEntityToolBar(i_toolbar);

		return i_toolbar;
	},

	createFilterBar: function() {

		var i_self = this;
		var o_entity = i_self.getEntity();
		var s_dmd = i_self.getDmdName();
		var b_filterMenu = i_self.getAllowMenuOnFilters();

		var b_allowMenu = (
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".functions.filter") ||
			Portfolio.util.Handler.isAccessible("app." + s_dmd + ".functions." + o_entity.name + ".filter.use")
		);

		if (b_allowMenu) {
			b_allowMenu = i_self.getAllowFilterMenu();
		}

		var i_filterbar = Ext.widget("filterbar", {
			dock: "top",
			grid: i_self,
			allowMenu: b_allowMenu,
			allowFilterMenu: b_filterMenu,
			hidden: true,
			defaultFilter: i_self.getDefaultFilter() || ""
		});
		i_self.setFilterBar(i_filterbar);

		return i_filterbar;
	},

	createToolbars: function() {

		var i_self = this;
		var a_return = [];
		if (i_self.getAllowActions()) {
			a_return.push(i_self.createToolbar());
		}
		if (i_self.getFilterable()) {
			a_return.push(i_self.createFilterBar());
		}

		return a_return;
	},

	/**
	 * saveInitialSetting..
	 * Saves the the state off the grid if the state of the never has been saved before or
	 * if the grid columns count in the dmd is changed
	 * grid: me.grid  THIS IS THE GRID THAT IS MADE DURING THE initComponent.
	 **/
	saveInitialSetting: function (i_store) {

		var i_self = this;
		var o_setting = {
			columns: {
				order: [],
				size: []
			}
		};
		var a_return = [];

		var a_columns = i_self.getColumns(i_store);

		Ext.Array.each(a_columns, function(o_column) {

			var o_copy = Ext.apply({}, {
				dataIndex: o_column.dataIndex || o_column.name,
				hidden: o_column.hidden
			});
			if (!o_column.hide) {
				a_return.push(o_column);
			}
			o_setting.columns.order.push(o_copy);
		});

		Portfolio.util.Handler.profile.set(i_self.getProviderID() + ".setting", JSON.stringify(o_setting));

		return a_return;
	},

	saveState: function() {

		var i_self = this;
		var s_id = i_self.getProviderID();

		if (!i_self.isDestroyed) {
			var a_columns = i_self.columnsConfig.slice(0);
			var a_headerColumns = i_self.getColumnManager().getColumns();

			a_headerColumns = Ext.Array.filter(a_headerColumns, function(i_col) {
				return i_col.dataIndex !== "";
			});

			var o_setting = Portfolio.util.Handler.profile.get(s_id + ".setting", {
				columns: {
					order: [],
					size: []
				}
			}); // USE THIS WHEN YOU WANT TO LOAD THE MODEL FROM DB

			Ext.applyIf(o_setting, {
				columns: {
					order: [],
					size: []
				}
			});

			o_setting.columns.order = [];
			o_setting.columns.size = [];

			Ext.Array.each(a_headerColumns, function(i_column) {
				o_setting.columns.order.push({
					dataIndex: i_column.dataIndex,
					hidden: i_column.hidden
				});
			});

			Ext.Array.each(a_columns, function(i_column) {
				var b_found = false;
				Ext.Array.each(a_headerColumns, function(i_header) {
					if (i_header.dataIndex == i_column.dataIndex) {
						b_found = true;
					}
				});
				if (!b_found) {
					o_setting.columns.order.push({
						dataIndex: i_column.dataIndex,
						hidden: i_column.hidden
					});
				}
			});

			Ext.Array.each(a_headerColumns, function(i_column) {
				o_setting.columns.size.push({
					dataIndex: i_column.dataIndex,
					width: i_column.width
				});
			});

			Ext.Array.each(a_columns, function(i_column) {
				var b_found = false;
				Ext.Array.each(a_headerColumns, function(i_header) {
					if (i_header.dataIndex == i_column.dataIndex) {
						b_found = true;
					}
				});
				if (!b_found) {
					o_setting.columns.size.push({
						dataIndex: i_column.dataIndex,
						width: i_column.width
					});
				}
			});

			Portfolio.util.Handler.profile.set(s_id + ".setting", JSON.stringify(o_setting));
		}
	},

	applyReset: function () {

		var i_self = this;
		var i_menu = i_self.headerCt.getMenu();

		i_menu.on({
			beforeshow: {
				fn: function(i_menu) {

					var i_reset = i_menu.getComponent("btnReset");

					if (!i_reset) {
						i_menu.add(i_self.createResetButton());
					}
				}
			}
		});
	},

	createResetButton: function () {

		var i_self = this;

		var i_button = Ext.widget("menuitem", {
			itemId: "btnReset",
			iconCls: "pf-arrow_circle2",
			text: Portfolio.util.Handler.i18n({
				en: "Reset",
				da: "Nulstil"
			}),
			handler: function () {
				i_self.resetSetting();
			}
		});
		return i_button;
	},

	createSearchButton: function () {

		var i_self = this;

		var i_button = Ext.widget("menuitem", {
			itemId: "btn_search",
			iconCls: "icon-gear",
			text: Portfolio.util.Handler.i18n({
				en: "Search",
				da: "Søg"
			}),
			handler: function (i_menuitem) {

				var i_column = i_menuitem.up("gridcolumn");

				i_self.fireEvent("colToSearch", i_self, i_column);
			}
		});
		return i_button;
	},

	resetSetting: function () {

		var i_self = this;
		var a_reconfig = i_self.saveInitialSetting();

		i_self.reconfigure(undefined, a_reconfig);
	},

	deleteRow: function (a_records) {

		var i_self = this;
		var i_store = i_self.getStore();
		var o_modelConfig = i_self.getModelConfig();
		var o_entityInfo = i_self.getEntityInfo();
		var o_dmd = o_entityInfo.dmd;
		var o_model = o_dmd.model;
		var o_proxy = o_model.proxy || {};

		o_proxy.portfolio = o_proxy.hasOwnProperty("portfolio") ? o_proxy.portfolio : true;

		var o_entity = i_self.getEntity();

		var s_message = a_records.length == 1 ? Portfolio.util.Handler.i18n({
			da: "Ønsker du virkelig at slette?",
			en: "Do you really wish to delete?"
		}) : Portfolio.util.Handler.i18n({
			da: "Ønsker du virkelig at slette de " + a_records.length + " valgte?",
			en: "Do you really wish to delete the " + a_records.length + " selected?"
		});

		ip2.messageBox({
			title: ip2.i18n({
				da: "Bekræft sletning",
				en: "Confirm deleting"
			}),
			icon: Ext.MessageBox.INFO,
			message: s_message,
			yesFn: function() {

				if (o_proxy.portfolio) {
					var a_batch = [];

					Ext.Array.each(a_records, function (i_record) {

						var o_keys = {};

						o_keys[i_record.idProperty] = i_record.get(i_record.idProperty);

						a_batch.push({
							type: "delete",
							dmd: o_modelConfig.dmd,
							entity: o_entity.name,
							key: o_keys
						});
					});

					s_message = Portfolio.util.Handler.i18n({
						da: "Sletter...",
						en: "Deleting..."
					});

					i_self.setLoading(s_message);

					Ext.Ajax.request({
						url: "/ip2-Services/ip2dmdproxy.aspx",
						jsonData: {
							batch: a_batch
						},
						success: function (o_response) {
							i_self.setLoading(false);

							i_store.load();
							i_self.fireEvent("afterdelete", i_store, a_records);
						}
					});
				}
				else {
					i_store.erase({
						records: a_records,
						callback: function() {
							i_self.setLoading(false);

							i_store.load();

							i_self.fireEvent("afterdelete", i_store, a_records);
						}
					});
				}
			},
			yesText: ip2.i18n({
				da: "Ok",
				en: "OK"
			}),
			cancelText: ip2.i18n({
				da: "Annuller",
				en: "Cancel"
			})
		});
	},

	upsertRecord: function(i_record, f_callback) {

		f_callback = f_callback || Ext.emptyFn;

		var i_self = this;
		var i_model = i_self.getModel();
		var o_entity = i_self.getEntity();
		var a_records = Ext.Array.from(i_record);
		var a_batch = [];

		Ext.Array.each(a_records, function(i_record) {

			var o_keys = {};

			o_keys[i_record.idProperty] = i_record.get(i_record.idProperty);

			var o_batch = {
				type: "upsert",
				dmd: i_model.dmdFile,
				entity: o_entity.name,
				transactiontype: o_entity.name,
				key: o_keys,
				transactionkey: i_record.get(i_record.idProperty),
				row: i_record.getData()
			};

			a_batch.push(o_batch);
		});

		Ext.Ajax.request({
			url: "/ip2-services/ip2dmdProxy.aspx",
			jsonData: {
				batch: a_batch
			},
			success: function (o_response) {
				f_callback();
			},
			failure: function(o_error) {
				f_callback();
			}
		});
	},

	getUpdatedRecord: function(i_record, f_callback) {

		f_callback = f_callback || Ext.emptyFn;

		var i_self = this;
		var i_model = i_self.getModel();
		var o_entity = i_self.getEntity();

		Ext.Ajax.request({
			url: "/ip2-services/ip2dmdProxy.aspx",
			params: {
				action: "getRows",
				context: "grid",
				dmdFile: i_model.dmdFile,
				uiName: i_self.getUiName(),
				model: o_entity.name,
				where: [
					i_record.idProperty,
					i_record.get(i_record.idProperty)
				].join(" = ")
			},
			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];

				var i_store = i_self.getStore();
				if (i_store) {
					var i_proxy = i_store.getProxy();
					var i_reader = i_proxy.getReader();
	
					var a_extracted = i_reader.extractData([o_data], {});
	
					var i_extracted = a_extracted[0];
	
					var o_extracted = i_extracted.getData();
	
					f_callback(o_extracted);
				}
				else {
					f_callback({});
				}
			},
			failure: function() {
				f_callback({});
			}
		});
	},

	getFormRecord: function(i_record, f_callback) {

		f_callback = f_callback || Ext.emptyFn;

		var i_self = this;
		var i_model = i_self.getModel();
		var o_entity = i_self.getEntity();

		var i_formModel = ip2.model({
			dmd: i_model.dmdFile,
			view: i_self.getUiName(),
			entity: o_entity.name,
			context: "form"
		});

		var o_keys = {};
		o_keys[i_record.idProperty] = i_record.get(i_record.idProperty);

		Ext.Ajax.request({
			url: "/ip2-services/ip2dmdProxy.aspx",
			params: {
				action: "getRow",
				context: "form",
				dmdFile: i_model.dmdFile,
				uiName: "portfolio",
				model: o_entity.name,
				key: Ext.encode(o_keys)
			},
			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];

				var i_record = i_formModel.create(o_data);

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

				var i_record = i_formModel.create({});

				f_callback(i_record);
			}
		});
	},

	createFeatures: function(a_features) {

		a_features = Ext.Array.filter(a_features, function(s_feature) {
			return s_feature;
		});

		var a_return = [];

		Ext.Array.each(a_features, function(s_feature) {

			var o_feature = {
				ftype: s_feature
			};
			switch(s_feature) {
				case "grouping":

					var i_template  = Ext.create("Ext.XTemplate",
						"<strong><span>{name} </span><span style=\"",
							"float:right;",
							"padding-left:10px;",
							"width: 90px;",
							"text-align: center;",
							"\">{[this.getCount(values)]}</span></strong>",
						{
							getCount: function(values) {
								return Ext.Array.from(values.rows).length;
							}
						}
					);

					Ext.apply(o_feature, {
						groupHeaderTpl: i_template,
						startCollapsed: true,
						groupByText: ip2.i18n({
							da: "Gruppér",
							en: "Group by"
						}),
						showGroupsText: ip2.i18n({
							da: "Vis gruppering",
							en: "Show grouping"
						})
					});

					break;
			}

			a_return.push(o_feature);
		});

		return a_return;
	},

	createKeyEvents: function() {

		var i_self = this;

		var a_bindings = [
			{
				key: Ext.event.Event.ENTER,
				fn: function (n_key, i_event) {

					var i_selected = i_self.getSelection()[0];

					if (i_selected) {
						i_self.handleAction(i_selected, "update", 0);
					}
				}
			},
		];

		var i_keyMap = Ext.create("Ext.util.KeyMap", {
			target: i_self.view.getEl(),
			binding: a_bindings
		});

		i_self.on({
			beforedestroy: {
				fn: function() {
					i_keyMap.destroy();
				},
				single: true
			}
		});
	}
});
