Ext.define("Portfolio.designer.ui.domainModelEntityGridLayout", {
	extend: "Ext.grid.Panel",
	alias: ["widget.ip2DomainModelEntityGridLayout"],
	border: 0,

	config: {
		designer: null,
		uiColumns: null,
		uiView: null,
		sort: "",
		filterBar: null,
		entity: null,
		entityManager: null,
		columnManager: null,
		fields: [],
		relations: [],
		oldRelations: [],
		menuCreated: false,
		columnKeys: [],
		required: false,
		pageSize: 100,
		purgePageCount: 5
	},

	requires: [
		"Portfolio.designer.ui.views.grid.column.Manager"
	],

	listeners: {
		newColumns: {
			fn: function(i_grid) {
				var i_self = this;
				i_self.addNewColumns();
			}
		},
		newRelations: {
			fn: function() {
				var i_self = this;
				i_self.syncColumns();
			}
		},
		updateRelation: {
			fn: function(i_grid, i_record) {

				var i_self = this;
				i_self.syncColumns();
			}
		},
		updateColumn: {
			fn: function(s_old, s_new) {

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

				if (a_columns.length === 0) {
					a_columns = i_self.columns;
				}

				var a_reconfigure = [];

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

					var o_column = i_column.initialConfig;

					if (i_column.dataIndex == s_old) {

						Ext.apply(o_column, {
							name: s_new,
							dataIndex: s_new
						});
					}

					a_reconfigure.push(o_column);
				});

				i_self.reconfigure(null, a_reconfigure);
			}
		},
		removeColumn: {
			fn: function(s_column) {

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

				if (a_columns.length === 0) {
					a_columns = i_self.columns;
				}

				var a_reconfigure = [];

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

					if (i_column.dataIndex != s_column) {

						var o_column = i_column.initialConfig;
						a_reconfigure.push(o_column);
					}
				});

				i_self.reconfigure(null, a_reconfigure);
			}
		},
		removeRelation: {
			fn: function(i_grid, s_entity) {

				var i_self = this;
				i_self.removeRelation(s_entity);
			}
		},
		columnhide: {
			fn: function(i_header, i_column) {

				var i_self = this;

				var i_filterBar = i_self.getFilterBar();

				var i_filter = i_filterBar.getFilterByDataIndex(i_column.dataIndex);

				if (i_filter) {
					i_filterBar.removeFilter(i_filter);
				}
			}
		},
		sortchange: {
			fn: function(i_header, i_column, s_direction) {

				var i_self = this;

				if (i_self.getFilterBar()) {
					i_self.getFilterBar().sortChange(i_column);
				}
			}
		}
	},

	initComponent: function() {

		var i_self = this;

		var i_designer = i_self.getDesigner();
		var o_model = i_designer.model;
		var i_entityManager = i_self.getEntityManager();
		var i_columnManager = i_entityManager.getColumnManager();

		var b_required = i_self.getRequired();

		var a_uiColumns = i_self.getUiColumns() || [];

		var i_columnGrid = i_columnManager.columnGrid;
		var i_columnStore = i_columnGrid.getStore();
		var o_uirules = ip2.loadUItypes();

		var b_noColumns = a_uiColumns.length === 0;
		var b_allHidden = true;

		var a_fields = [];

		var a_columns = [];

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

			var o_entity = i_self.getEntity();

			var o_clone = Ext.clone(o_uiColumn);

			var i_entityColumn = i_columnStore.getById(o_clone.name);

			var o_entityColumn = i_entityColumn ? i_entityColumn.getData() : {};

			var o_column = Ext.apply({
				entity: o_entity.name,
				menuDisabled: b_required,
				draggable: !b_required,
				showned: o_clone.showned || true,
				dataOnly: o_clone.hide || false,
				isTitle: o_clone.isTitle || false,
				from: o_uiColumn.from
			}, o_clone);

			delete o_column.hide;

			if (o_column.mapping) {
				o_column.name = o_column.mapping.split(".").join("_");
			}

			var s_dataIndex = o_column.as || o_column.name;

			var f_renderer = function(value) {

				return value;
			};

			if (o_column.uitype && o_uirules[o_column.uitype]) {

				var o_rule = o_uirules[o_column.uitype];

				if (o_rule.grid) {
					if (o_rule.grid.renderer) {
						f_renderer = o_rule.grid.renderer;
					}

					if (o_rule.grid.xtype) {
						o_column.xtype = o_rule.grid.xtype;
					}
				}

			}


			if (!o_clone.showned) {
				o_column.hidden = false;
			}
			else {
				b_allHidden = false;
			}

			if (Ext.Array.indexOf(i_self.columnKeys, s_dataIndex) === -1) {

				i_self.columnKeys.push(s_dataIndex);

				if (!Ext.Object.isEmpty(o_entityColumn)) {

					var s_title = o_clone.title ? ip2.i18n(o_clone.title) : ip2.i18n(o_entityColumn.title);

					s_title = s_title || "";

					Ext.apply(o_column, {
						dataIndex: s_dataIndex,
						header: s_title,
						headerText: s_title,
						flex: o_uiColumn.width ? 0 : 1
					});

					if (o_column.isTitle) {
						s_title = "<strong>" + s_title + "</strong>";

						Ext.apply(o_column, {
							header: s_title
						});
					}

					o_column.columnConfig = Ext.clone(o_column);

					if (!o_column.xtype) {
						Ext.apply(o_column, {
							renderer: f_renderer
						});
					}

					a_columns.push(o_column);

					a_fields.push({
						name: o_column.dataIndex,
						mapping: o_column.mapping || null,
						type: "auto"
					});
				}
				else {

					if (!o_clone.showned) {
						o_column.hidden = false;
					}

					var o_result = Ext.Object.merge({}, o_column, {
						dataIndex: s_dataIndex,
						header: ip2.i18n(o_clone.title),
						headerText: ip2.i18n(o_clone.title),
						showned: o_clone.showned || true,
						dataOnly: o_clone.hide || false,
						isTitle: o_clone.isTitle || false,
						flex: 1
					}, o_clone);

					if (o_result.isTitle) {
						var s_title = ip2.i18n(o_clone.title);
						s_title = "<strong>" + s_title + "</strong>";

						Ext.apply(o_result, {
							header: s_title
						});
					}

					delete o_result.hide;

					o_result.columnConfig = Ext.clone(o_result);

					if (!o_result.xtype) {
						Ext.apply(o_column, {
							renderer: f_renderer
						});
					}

					a_columns.push(o_result);

					a_fields.push({
						name: s_dataIndex,
						mapping: o_result.mapping || null,
						type: "auto"
					});
				}
			}
		});

		// Add remaining entity columns, not add grid column model
		var a_records = i_columnStore.getRange();

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

			if (Ext.Array.indexOf(i_self.columnKeys, i_record.get("name")) == -1) {

				var f_renderer = function(value) {
					return value;
				};

				var s_uitype = i_record.get("uitype");

				if (s_uitype && o_uirules[s_uitype]) {

					var o_rule = o_uirules[s_uitype];

					if (o_rule.grid) {
						if (o_rule.grid.renderer) {
							f_renderer = o_rule.grid.renderer;
						}
					}
				}

				var o_column = {
					header: ip2.i18n(i_record.data.title),
					dataIndex: i_record.get("name"),
					name: i_record.get("name"),
					hidden: true,
					flex: 1
				};

				if (!o_column.xtype) {
					Ext.apply(o_column, {
						renderer: f_renderer
					});
				}

				if (b_noColumns) {
					o_column.hidden = false;
					b_noColumns = false;
				}

				a_columns.push(o_column);

				a_fields.push({
					name: o_column.dataIndex,
					type: "auto"
				});
			}
		});

		if (b_allHidden && a_columns.length > 0) {

			var o_column = a_columns[0];

			Ext.apply(o_column, {
				showned: true,
				hidden: false,
				dataOnly: false
			});
		}

		var o_entity = i_self.getEntity();

		var s_dmd = "dmd/" + i_designer.dmdFile.split("/").pop();

		var a_url = [];

		a_url.push(o_model.proxy.defaultHive || "");

		a_url.push(o_model.proxy.url);

		a_url.filter(function(s_value) {
			return s_value;
		});

		var i_model = Ext.define(ip2.unique("entity-model-" + i_self.getUiView()), {
			extend: "Ext.data.Model",
			fields: a_fields,
			proxy: ip2.getProxyByEntity({
				dmd: s_dmd,
				entity: o_entity.name,
				view: i_self.getUiView(),
				context: "grid",
				model: o_model
			})
		});

		var i_store = Ext.create("Ext.data.BufferedStore", {
			model: i_model,
			remoteSort: true,
			autoLoad: false,
			pageSize: i_self.getPageSize(),
			purgePageCount: i_self.getPurgePageCount(),
			listeners: {
				beforeload: {
					fn: function(i_store, i_operation) {

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

						var o_sorters = i_store.getSorters();
						var a_sort = [];

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

							var s_sorter = o_sort.getProperty() + " " + o_sort.getDirection();
							a_sort.push(s_sorter);
						});

						Ext.apply(o_extraParams, {
							sort: a_sort.join(", "),
							dir: "",
							scroll: true
						});
					}
				}
			}
		});

		i_self.store = i_store;
		i_self.columns = a_columns;

		i_self.setFields(a_fields);

		i_self.callParent();

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

		if (o_view) {
			var a_filters = o_view.filters || [];

			if (a_filters.length === 0) {

				var o_sorters = i_store.getSorters();

				var s_sort = i_self.getSort();
				var a_sorters = [];

				if (s_sort) {

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

					o_sorters.add(a_sorters);
				}
			}
		}

		var i_menu = i_self.headerCt.getMenu();

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

					var n_length = i_menu.items.getCount();
					var i_activeHeader = i_menu.activeHeader;
					var a_add = [];

					var i_columnItem = i_menu.child("#columnItem");
					var i_columnMenu = i_columnItem.menu;

					var i_title = i_menu.child("#column-title");
					var i_visibleParent = i_menu.child("#column-visible-menu");
					var i_deleteItem = i_menu.child("#column-delete");
					var i_editItem = i_menu.child("#column-edit");
					var i_addeItem = i_menu.child("#column-add");

					var n_index = i_menu.items.findIndexBy(function(i_item) {
						return i_item.itemId == "descItem";
					});

					i_columnMenu.removeAll(true);

					var n_removeIndex = i_menu.items.findIndexBy(function(i_item) {
						return i_item.itemId == "columnItem";
					});

					if (n_removeIndex + 1 != n_length) {

						var a_remove = i_menu.items.getRange(n_removeIndex + 1);
						Ext.Array.each(a_remove, function(i_item) {
							i_menu.remove(i_item);
						});
					}

					var a_items = i_self.headerCt.getColumnMenu(i_self.headerCt);
					var a_columns = i_self.getColumnManager().getColumns();

					var a_entityColumns = o_entity.columns;
					var b_found = false;

					Ext.Array.each(a_entityColumns, function(o_column) {
						if (o_column.name == i_menu.ownerCmp.dataIndex) {
							b_found = true;
							return false;
						}
					});

					var n_count = 0;

					Ext.Array.each(a_columns, function(i_column) {
						if (!i_column.hidden) {

							i_column.showned = i_column.showned !== undefined ? i_column.showned : true;
							i_column.dataOnly = i_column.dataOnly !== undefined ? i_column.dataOnly : false;

							if (i_column.showned && !i_column.dataOnly) {
								n_count++;
							}
						}
					});

					if (a_items.length == 1) {
						a_items[0].disable();
					}
					else {

						var n_checked = 0;
						var i_checked;

						Ext.Array.each(a_items, function(i_item) {
							if (i_item.checked) {
								i_checked = i_item;
								n_checked++;
							}
						});

						if (n_checked == 1) {
							i_checked.disable();
						}
					}

					if (i_title) {
						i_menu.remove(i_title);
					}

					if (i_visibleParent) {
						i_menu.remove(i_visibleParent);
					}

					if (i_deleteItem) {
						i_menu.remove(i_deleteItem);
					}

					if (i_editItem) {
						i_menu.remove(i_editItem);
					}

					if (i_addeItem) {
						i_menu.remove(i_addeItem);
					}

					if (!b_found) {
						i_deleteItem = Ext.widget("menuitem", {
							itemId: "column-delete",
							text: ip2.i18n({
								da: "Slet",
								en: "delete"
							}),
							grid: i_self,
							column: i_menu.ownerCmp,
							iconCls: "pf-delete",
							handler: function(i_menuitem) {

								var i_column = i_menuitem.column;
								var i_grid = i_menuitem.grid;

								ip2.messageBox({
									title: ip2.i18n({
										da: "Advarrelse",
										en: "Warning"
									}),
									message: ip2.i18n({
										da: "Vil du slette <br/><strong>" + i_column.text + "</strong>...?",
										en: "Do you want to delete <br/><strong>" + i_column.text + "</strong>...?"
									}),
									yesFn: function() {
										i_grid.removeColumn(i_column.dataIndex);
									},
									yesText: ip2.i18n({
										da: "Ok",
										en: "OK"
									}),
									cancelText: ip2.i18n({
										da: "Annuller",
										en: "Cancel"
									})
								});
							}
						});
						a_add.unshift(i_deleteItem);
					}

					var b_showned = Ext.isBoolean(i_activeHeader.showned) ? i_activeHeader.showned : true;
					var b_hide = Ext.isBoolean(i_activeHeader.dataOnly) ? i_activeHeader.dataOnly : false;

					if (b_hide) {
						b_showned = false;
						i_activeHeader.showned = false;
						n_count--;
					}

					i_visibleItem = Ext.widget("menucheckitem", {
						itemId: "column-visible-item",
						text: ip2.i18n({
							da: "Tilvalgt",
							en: "Selected"
						}),
						grid: i_self,
						checked: b_hide ? false : b_showned,
						columnHeader: i_activeHeader,
						disabled: b_showned ? n_count === 1 ? true : false : b_hide ? true : false,
						hideOnClick: false,
						menu: undefined,
						checkHandler: function(i_menuitem, b_checked) {

							var i_header = i_menuitem.columnHeader;
							i_header.showned = b_checked;

							var i_grid = i_menuitem.grid;
							var i_headerCt = i_grid.headerCt;
							var i_menu = i_headerCt.getMenu();
							var i_childMenu = i_menu.child("#column-visible-menu");
							var i_hiddenItem = i_childMenu.child("#column-hidden-item");

							i_hiddenItem.setChecked(!b_checked, true);
						}
					});

					var i_hiddenItem = Ext.widget("menucheckitem", {
						itemId: "column-hidden-item",
						text: ip2.i18n({
							da: "Fravalgt",
							en: "Deselected"
						}),
						grid: i_self,
						checked: b_hide ? false : !b_showned,
						columnHeader: i_activeHeader,
						hideOnClick: false,
						disabled: b_showned ? n_count === 1 ? true : false : b_hide ? true : false,
						menu: undefined,
						checkHandler: function(i_menuitem, b_checked) {

							var i_header = i_menuitem.columnHeader;
							i_header.showned = !b_checked;

							var i_grid = i_menuitem.grid;
							var a_columns = i_grid.getColumnManager().getColumns();
							var i_headerCt = i_grid.headerCt;
							var i_menu = i_headerCt.getMenu();
							var i_childMenu = i_menu.child("#column-visible-menu");
							var i_visibleItem = i_childMenu.child("#column-visible-item");

							i_visibleItem.setChecked(!b_checked, true);
						}
					});

					var i_hideItem = Ext.widget("menucheckitem", {
						itemId: "column-hide-item",
						text: ip2.i18n({
							da: "Skjult",
							en: "Hidden"
						}),
						grid: i_self,
						checked: b_hide,
						disabled: b_showned ? n_count === 1 ? true : false : false,
						columnHeader: i_activeHeader,
						hideOnClick: false,
						menu: undefined,
						checkHandler: function(i_menuitem, b_checked) {

							var i_grid = i_menuitem.grid;
							var a_columns = i_grid.getColumnManager().getColumns();
							var i_headerCt = i_grid.headerCt;
							var i_menu = i_headerCt.getMenu();
							var i_childMenu = i_menu.child("#column-visible-menu");
							var i_visibleItem = i_childMenu.child("#column-visible-item");
							var i_hiddenItem = i_childMenu.child("#column-hidden-item");

							if (i_visibleItem) {
								if (b_checked) {
									i_visibleItem.setChecked(false, true);
								}
								i_visibleItem[b_checked ? "disable" : "enable"]();
							}

							if (i_hiddenItem) {
								if (b_checked) {
									i_hiddenItem.setChecked(false, true);
								}
								i_hiddenItem[b_checked ? "disable" : "enable"]();
							}

							var i_header = i_menuitem.columnHeader;
							i_header.dataOnly = b_checked;
						}
					});

					var i_visibleMenu = Ext.widget("menu", {
						items: [
							i_visibleItem,
							i_hiddenItem,
							i_hideItem
						]
					});

					i_visibleParent = Ext.widget("menuitem", {
						itemId: "column-visible-menu",
						text: ip2.i18n({
							da: "State",
							en: "State"
						}),
						iconCls: "pf-home",
						menu: i_visibleMenu
					});

					a_add.unshift(i_visibleParent);

					i_title = Ext.widget("menucheckitem", {
						itemId: "column-title",
						text: ip2.i18n({
							da: "Titel kolonne",
							en: "Title Column"
						}),
						grid: i_self,
						checked: i_activeHeader.isTitle,
						columnHeader: i_activeHeader,
						hideOnClick: false,
						menu: undefined,
						checkHandler: function(i_menuitem, b_checked) {

							var i_header = i_menuitem.columnHeader;
							i_header.isTitle = b_checked;
							var s_text = i_header.headerText;
							if (b_checked) {
								s_text = "<strong>" + s_text + "</strong>";
							}

							i_header.setText(s_text);
						}
					});

					a_add.unshift(i_title);

					i_editItem = Ext.widget("menuitem", {
						itemId: "column-edit",
						text: ip2.i18n({
							da: "Redigér",
							en: "Edit"
						}),
						grid: i_self,
						column: i_menu.ownerCmp,
						iconCls: "pf-edit",
						handler: function(i_menuitem) {

							var i_column = i_menu.ownerCmp;

							var o_config = i_menu.ownerCmp.columnConfig || i_menu.ownerCmp.initialConfig || {
								text: ""
							};

							Ext.apply(o_config, {
								title: i_column.title || i_column.headerText,
								isTitle: i_column.isTitle || false,
								uitype: i_column.uitype || undefined
							});

							var i_manager = Ext.widget("designer.ui.views.grid.column.manager", {
								title: ip2.i18n(i_column.title),
								width: 800,
								height: 600,
								entity: i_self.getEntity(),
								column: o_config,
								required: i_self.getRequired(),
								listeners: {
									edit: {
										fn: function(i_manager, o_result) {

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

											var a_reconfig = [];
											var b_found = false;

											var f_renderer = function (value) {

												return value;
											};

											var o_uirules = ip2.loadUItypes();

											if (o_result.uitype && o_uirules[o_result.uitype]) {

												var o_rule = o_uirules[o_result.uitype];

												if (o_rule.grid) {
													if (o_rule.grid.renderer) {
														f_renderer = o_rule.grid.renderer;
													}
												}

												if (o_rule.grid.xtype) {
													o_result.xtype = o_rule.grid.xtype;
												}
											}

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

												var o_config = i_column.initialConfig;

												if (!b_found && o_config.dataIndex == o_result.dataIndex) {
													o_config = Ext.apply(o_config, o_result);
													b_found = true;
												}

												Ext.applyIf(o_config, {
													mapping: i_column.mapping,
													isTitle: i_column.isTitle,
													hidden: i_column.hidden,
													title: ip2.i18n(i_column.title) || i_column.header,
													showned: i_column.showned !== undefined ? i_column.showned : true,
													dataOnly: i_column.dataOnly !== undefined ? i_column.dataOnly : false,
													renderer: i_column.renderer,
													from: i_column.from
												});

												if (i_column.hasOwnProperty("usingDefaultRenderer")) {
													Ext.apply(o_config, {
														usingDefaultRenderer: i_column.usingDefaultRenderer
													});

													delete o_config.renderer;
												}

												a_reconfig.push(o_config);
											});

											if (!o_result.xtype) {
												Ext.apply(o_result, {
													renderer: f_renderer
												});
											}
											else {
												delete o_result.renderer;
											}

											if (!b_found) {
												a_reconfig.push(o_result);
											}

											i_self.reconfigure(null, a_reconfig);

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

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

												var s_text = i_column.headerText;
												if (i_column.isTitle) {
													s_text = "<strong>" + s_text + "</strong>";
												}
												i_column.setText(s_text);
											});
										}
									}
								}
							});

							i_manager.show();
						}
					});

					a_add.unshift(i_editItem);

					i_addeItem = Ext.widget("menuitem", {
						itemId: "column-add",
						text: ip2.i18n({
							da: "Tilføj",
							en: "Add"
						}),
						grid: i_self,
						column: i_menu.ownerCmp,
						iconCls: "pf-add",
						handler: function(i_menuitem) {

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

							var i_manager = Ext.widget("designer.ui.views.grid.column.manager", {
								title: ip2.i18n({
									da: "Tilføj kolonne",
									en: "Add column"
								}),
								width: 800,
								height: 600,
								grid: i_grid,
								entity: o_entity,
								column: null,
								required: i_grid.getRequired(),
								listeners: {
									edit: {
										fn: function(i_manager, o_column) {

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

											var a_reconfig = [];
											var b_found = false;

											var f_renderer = function (value) {

												return value;
											};

											var o_uirules = ip2.loadUItypes();

											if (o_column.uitype && o_uirules[o_column.uitype]) {

												var o_rule = o_uirules[o_column.uitype];

												if (o_rule.grid) {
													if (o_rule.grid.renderer) {
														f_renderer = o_rule.grid.renderer;
													}
												}

												if (o_rule.grid.xtype) {
													o_column.xtype = o_rule.grid.xtype;
												}
											}

											if (!o_column.xtype) {
												Ext.apply(o_column, {
													renderer: f_renderer
												});
											}
											else {
												delete o_column.renderer;
											}


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

												var o_config = i_column.initialConfig;

												Ext.applyIf(o_config, {
													mapping: i_column.mapping,
													isTitle: i_column.isTitle,
													hidden: i_column.hidden,
													title: ip2.i18n(i_column.title) || i_column.header,
													showned: i_column.showned !== undefined ? i_column.showned : true,
													dataOnly: i_column.dataOnly !== undefined ? i_column.dataOnly : false,
													renderer: i_column.renderer,
													from: i_column.from
												});


												if (i_column.hasOwnProperty("usingDefaultRenderer")) {
													Ext.apply(o_config, {
														usingDefaultRenderer: i_column.usingDefaultRenderer
													});

													delete o_config.renderer;
												}


												a_reconfig.push(o_config);
											});

											a_reconfig.push(o_column);

											i_self.reconfigure(null, a_reconfig);

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

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

												var s_text = i_column.headerText;
												if (i_column.isTitle) {
													s_text = "<strong>" + s_text + "</strong>";
												}
												i_column.setText(s_text);
											});
										}
									}
								}
							});

							i_manager.show();
						}
					});

					a_add.unshift(i_addeItem);

					i_columnItem.menu.add(a_items);

					var i_separator = Ext.widget("menuseparator", {});
					var a_menus = i_self.createHeaderMenu();
					a_menus.unshift(i_separator);

					i_menu.insert(n_index + 1, a_add);

					i_menu.add(a_menus);
				}
			}
		});

		var i_filterbar = Ext.widget("filterbar", {
			dock: "top",
			grid: i_self,
			allowMenu: false,
			layout: {
				type: "hbox",
				align: "center"
			},
			style: {
				"padding": "5px 0 6px 5px !important"
			},
			defaultFilter: ""
		});

		i_filterbar.add(0, [{
			xtype: "button",
			iconCls: "pf-refresh",
			handler: function() {

				var i_store = i_self.getStore();

				i_store.loadPage(1);
			}
		}]);

		i_self.setFilterBar(i_filterbar);

		i_self.addDocked(i_filterbar);

		i_self.syncColumns();

		var i_header = i_self.headerCt;

		i_header.on({
			boxready: {
				fn: function(i_item) {

					var i_filterbar = i_self.getFilterBar();
					var o_entity = i_self.getEntity();
					var o_view = o_entity.ui.grids[i_self.getUiView()];
					if (o_view) {
						var a_filters = o_view.filters || [];

						if (i_filterbar) {
							var s_ddGroup = i_header.reorderer.dragZone.ddGroup;

							i_filterbar.dd.addDDGroup(s_ddGroup);

							if (a_filters.length > 0) {
								i_filterbar.loadFilters(a_filters);
							}
						}
					}
				}
			}
		});
	},
	syncColumns: function () {

		var i_self = this;
		var i_designer = i_self.getDesigner();
		var o_model = i_designer.model;
		var o_currentEntity = i_self.getEntity();
		var i_entityManager = i_self.getEntityManager();
		var i_relationManager = i_entityManager.getRelationManager();
		var i_columnManager = i_self.getColumnManager();

		var a_relations = i_relationManager.getParentRelation();
		var a_entities = o_model.required;

		var a_columns = i_columnManager ? i_columnManager.getColumns() : i_self.columns;
		var a_handled = [];
		var a_new = [];

		var o_uirules = ip2.loadUItypes();

		Ext.Array.each(a_relations, function (o_relation) {

			var s_entity = o_relation.andEntity != o_currentEntity.name ? o_relation.andEntity : o_relation.betweenEntity;
			var o_properties = o_relation.properties || {};

			var s_cardinality = o_relation.cardinality;

			var o_entity = Ext.Array.findBy(a_entities, function (o_value) {

				return o_value.name == s_entity;
			});

			if (o_entity && (s_cardinality == "one2one" || s_cardinality == "many2one")) {

				o_entity.name = o_entity.name || o_relation.entityName || o_relation.betweenEntity;

				var asTitle = ip2.i18n(o_entity.title);

				Ext.Array.each(o_entity.columns, function (o_entityColumn) {

					var s_dataIndex = o_properties.as || [o_entity.name, o_entityColumn.name].join("_");

					var i_column = Ext.Array.findBy(a_columns, function (i_search) {
						return i_search.dataIndex == s_dataIndex;
					});

					var o_column;

					if (!i_column) {

						var s_title = asTitle;

						if (s_title) {
							if (o_entityColumn.title) {
								s_title = s_title + " - " + ip2.i18n(o_entityColumn.title);
							}
						}
						else {
							s_title = ip2.i18n(o_entityColumn.title);
						}

						var f_renderer = function (value) {
							return value;
						};

						var s_type = o_entityColumn.type;
						var o_type = o_uirules[s_type];

						if (o_entityColumn.uitype) {
							s_type = o_entityColumn.uitype;
						}

						if (o_type && o_type.grid) {
							f_renderer = o_type.grid.renderer;
						}

						var o_column = {
							header: ip2.i18n(s_title),
							name: o_entityColumn.name,
							entity: o_entity.name,
							mapping: o_properties.as ? o_properties.as + "." + s_dataIndex : "",
							title: s_title,
							hidden: true,
							flex: 1,
							from: o_entity.name,
							dataIndex: s_dataIndex
						};

						if (o_type && o_type.grid) {
							o_column.xtype = o_type.grid.xtype;
						}

						if (!o_column.xtype) {
							Ext.apply(o_column, {
								renderer: f_renderer
							});
						}

						a_new.push(o_column);
						a_handled.push(s_dataIndex);
					}
					else {
						o_column = Ext.clone(i_column.columnConfig || i_column.initialConfig);

						Ext.apply(o_column, {
							from: o_entity.name,
							hidden: true
						});

						a_new.push(o_column);
					}
				});
			}
		});

		var a_old = [];

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

			var o_column = Ext.clone(i_column.columnConfig || i_column.initialConfig);

			Ext.applyIf(o_column, {
				mapping: i_column.mapping,
				isTitle: i_column.isTitle,
				hidden: i_column.hidden,
				title: ip2.i18n(i_column.title) || i_column.header,
				showned: i_column.showned !== undefined ? i_column.showned : true,
				dataOnly: i_column.dataOnly !== undefined ? i_column.dataOnly : false,
				renderer: i_column.renderer,
				from: i_column.from
			});

			if (i_column.hasOwnProperty("usingDefaultRenderer")) {
				Ext.apply(o_column, {
					usingDefaultRenderer: i_column.usingDefaultRenderer
				});
			}

			a_old.push(o_column);
		});

		var a_result = a_old.concat(a_new);

		Ext.Array.each(a_result, function (o_column) {
			if (i_self.getRequired()) {
				Ext.apply(o_column, {
					menuDisabled: true,
					draggable: false
				});
			}
		});

		i_self.reconfigure(null, a_result);
	},

	createHeaderMenu: function () {

		var i_self = this;
		var i_designer = i_self.getDesigner();
		var o_model = i_designer.model;

		var a_menus = [];
		var a_items = [];

		var i_entityManager = i_self.getEntityManager();
		var i_relationManager = i_entityManager.getRelationManager();
		var i_propertyManager = i_entityManager.getEntityPropertyManager();
		var i_columnManager = i_entityManager.getColumnManager();
		var i_columnGrid = i_columnManager.columnGrid;
		var i_columnStore = i_columnGrid.getStore();
		var a_records = i_columnStore.getRange();

		var i_form = i_propertyManager.getForm();
		var o_formValues = i_form.getFieldValues();

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

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

			var s_dataIndex = i_record.get("name");
			var b_visible = i_self.columnIsVisible(s_dataIndex);

			var o_value = Ext.widget("menucheckitem", {
				text: ip2.i18n(i_record.get("title")),
				dataIndex: s_dataIndex,
				checked: b_visible,
				entity: o_formValues.name,
				checkHandler: function(i_menuitem, b_checked) {

					var i_columnManager = i_self.getColumnManager();
					var a_columns = i_columnManager.getColumns();
					var i_parent = i_menuitem.parentMenu;

					var i_found = Ext.Array.findBy(a_columns, function(i_column) {
						return Ext.isEmpty(i_column.from) && i_column.dataIndex == i_menuitem.dataIndex;
					});

					if (i_found) {
						i_found[b_checked ? "show" : "hide"]();
					}

					var a_visible = i_visibleManager.getColumns();
					var a_items = i_parent.items.getRange();

					Ext.Array.each(a_columns, function(i_column) {
						if (!i_column.hidden) {
							i_column.enable();
						}
					});

					if (a_visible.length == 1) {
						var i_column = a_query[0];
						if (i_column) {
							i_column.disable();
						}
					}
				}
			});

			a_items.push(o_value);
		});

		var i_menu = Ext.widget("menuitem", {
			text: ip2.i18n(o_formValues.title),
			iconCls: "pf-table_selection_column",
			menu: Ext.widget("menu", {
				items: a_items
			})
		});

		a_menus.push(i_menu);

		var a_relations = i_relationManager.getParentRelation();
		var a_entities = o_model.required;

		Ext.Array.each(a_relations, function(o_relation) {

			var s_entity = o_relation.entityName;
			var o_properties = o_relation.properties || {};

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

			var a_items = [];

			var s_part = s_entity;

			var s_cardinality = o_relation.cardinality;

			if((s_cardinality == "one2one" || s_cardinality == "many2one")) {

				Ext.Array.each(o_entity.columns, function (o_column) {

					var s_dataIndex = o_properties.as || [s_part, o_column.name].join("_");

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

					var i_menuitem = Ext.widget("menucheckitem", {
						text: ip2.i18n(o_column.title),
						checked: i_found ? !i_found.hidden : false,
						name: s_dataIndex,
						grid: i_self,
						dataIndex: s_dataIndex,
						checkHandler: function (i_menuitem, b_checked) {

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

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

							if (i_found) {
								i_found[b_checked ? "show" : "hide"]();
							}
						}
					});

					a_items.push(i_menuitem);
				});

				var s_title = ip2.i18n(o_entity.title);

				var i_menu = Ext.widget("menuitem", {
					text: s_title,
					iconCls: "ip2-gridLayout-entity",
					menu: Ext.widget("menu", {
						items: a_items
					})
				});

				a_menus.push(i_menu);
			}
		});

		return a_menus;
	},

	columnIsVisible: function(s_name) {

		var i_self = this;
		var i_columnManager = i_self.getVisibleColumnManager();

		var a_columns = i_columnManager.getColumns();

		var i_column = Ext.Array.findBy(a_columns, function(i_column) {
			return i_column.dataIndex == s_name || i_column.as == s_name;
		});

		return i_column ? !i_column.hidden : false;
	},

	addNewColumns: function() {

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

		var a_new = [];
		var a_current = i_self.getColumnManager().getColumns();
		var i_entityManager = i_self.getEntityManager();
		var i_columnManager = i_entityManager.getColumnManager();
		var i_columnGrid = i_columnManager.columnGrid;
		var i_store = i_columnGrid.getStore();
		var a_records = i_store.getRange();

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

			var i_found = Ext.Array.findBy(a_current, function(i_column) {
				return i_column.dataIndex == i_record.get("name");
			});

			if (!i_found) {

				var o_column = Ext.apply({}, {
					title: ip2.i18n(i_record.get("title")),
					header: ip2.i18n(i_record.get("title")),
					name: i_record.get("name"),
					dataIndex: i_record.get("name"),
					entity: o_entity.name,
					hidden: true,
					showned: false,
					dataOnly: false,
					flex: 1
				});

				a_new.push(o_column);
			}
		});

		if (a_new.length > 0) {

			var a_old = [];

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

				var o_column = {};

				var a_keys = Ext.Object.getKeys(i_column.config);

				Ext.Array.each(a_keys, function(s_key) {
					var value = i_column.config[s_key];
					if (!Ext.grid.Column.prototype.hasOwnProperty(s_key)) {
						o_column[s_key] = value;
					}
				});

				Ext.apply(o_column, {
					title: ip2.i18n(i_column.title) || i_column.header,
					hidden: i_column.hidden,
					showned: i_column.showned !== undefined ? i_column.showned : true,
					dataOnly: i_column.dataOnly !== undefined ? i_column.dataOnly : false
				});

				if (i_column.width) {
					o_column.width = i_column.width;
					delete o_column.flex;
				}
				else {
					o_column.flex = i_column.flex;
					delete o_column.width;
				}

				Ext.Object.each(o_column, function(s_key, value) {

					if (Ext.isEmpty(value)) {
						delete o_column[s_key];
					}
					if (Ext.isFunction(value)) {
						delete o_column[s_key];
					}

					if (value instanceof Ext.Component) {
						delete o_column[s_key];
					}
				});

				a_old.push(o_column);
			});

			var a_columns = a_old.concat(a_new);
			var b_hidden = true;

			Ext.Array.each(a_columns, function(o_column) {
				if (!o_column.hidden) {
					b_hidden = false;
				}
			});

			if (b_hidden && a_columns.length > 0) {
				var o_column = a_columns[0];

				o_column = Ext.apply(o_column, {
					showned: true,
					hidden: false,
					dataOnly: false
				});
			}

			i_self.reconfigure(null, a_columns);
		}
	},

	removeRelation: function(s_entity) {

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

		if (a_columns.length === 0) {
			a_columns = i_self.columns;
		}

		var a_reconfigure = [];

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

			if (i_column.entity != s_entity) {

				var o_column = {
					name: i_column.name,
					dataIndex: i_column.dataIndex,
					header: i_column.text,
					entity: i_column.entity,
					hidden: i_column.hidden
				};

				a_reconfigure.push(o_column);
			}
		});

		i_self.reconfigure(null, a_reconfigure);
	},

	removeColumn: function (s_column) {

		var i_self = this;
		i_self.fireEvent("removeColumn", s_column);
	},

	getModelConfig: function() {

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

		return {
			dmd: i_designer.dmdFile,
			entityName: o_entity.name,
			context: "grid",
			container: i_self,
			uiName: i_self.getUiView()
		};
	},

	updatePageSize: function(n_count) {

		var i_self = this;

		if (i_self.rendered) {

			var i_oldStore = i_self.getStore();

			var i_newStore = i_self.createStore();
			i_self.reconfigure(i_newStore, null, true);

			i_oldStore.destroy();

			i_newStore.loadPage(1);
		}
	},

	updatePurgePageCount: function(n_count) {

		var i_self = this;

		if (i_self.rendered) {

			var i_oldStore = i_self.getStore();

			var i_newStore = i_self.createStore();
			i_self.reconfigure(i_newStore, null, true);

			i_oldStore.destroy();

			i_newStore.loadPage(1);
		}
	},

	createStore: function() {

		var i_self = this;

		var i_currentModel = i_self.getStore().getModel();

		var i_store = Ext.create("Ext.data.BufferedStore", {
			model: i_currentModel,
			remoteSort: true,
			autoLoad: false,
			pageSize: i_self.getPageSize(),
			purgePageCount: i_self.getPurgePageCount(),
			listeners: {
				beforeload: {
					fn: function (i_store, i_operation) {

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

						var o_sorters = i_store.getSorters();
						var a_sort = [];

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

							var s_sorter = o_sort.getProperty() + " " + o_sort.getDirection();
							a_sort.push(s_sorter);
						});

						Ext.apply(o_extraParams, {
							sort: a_sort.join(", "),
							dir: "",
							scroll: true
						});
					}
				}
			}
		});

		return i_store;
	}
});
