Ext.define("Portfolio.designer.ui.form.layout.Tree", {

	extend: "Ext.tree.Panel",

	alias: "widget.form.designer.layout.tree",

	useArrows: true,

	rootVisible: true,

	multiSelect: false,

	singleExpand: false,

	split: true,

	config: {
		designer: null,
		entityManager: null,
		entity: null,
		context: "",
		keys: {},
		formCollections: [],
		definitions: [],
		collectionPicker: null
	},

	initComponent: function() {

		var i_self = this;

		i_self.setKeys({
			column: [],
			form: []
		});

		Ext.apply(i_self, {
			store: i_self.createStore(),
			columns: i_self.createColumns(),
			viewConfig: i_self.createViewConfig()
		});

		i_self.header = {
			titlePosition: 0,
			layout: {
				type: "hbox",
				align: "stretch"
			},
			items: i_self.addHeaderItems()
		};

		i_self.callParent(arguments);

		i_self.addListeners();

		i_self.enableBubble([
			"syncTrees",
			"collectionupdate"
		]);

	},

	createViewConfig: function() {

		var i_self = this;

		return {
			plugins: {
				ptype: "treeviewdragdrop",
				dropGroup: "form",
				dragGroup: "form",
				dropZone: {
					isValidDropPoint: function (node, position, dragZone, e, data) {

						var i_dropzone = this;
						var i_view = i_dropzone.view;
						var a_records = data.records;
						var b_allowed = false;
						var i_record = a_records[0];
						var i_overRecord = i_view.getRecord(node);

						if (i_overRecord && i_record.parentNode != i_overRecord) {

							var o_propertiesRecord = i_record.get("properties");
							var o_propertiesOver = i_overRecord.get("properties") || {};

							if (o_propertiesOver.nodeType == "tabs-root") {

								if (o_propertiesRecord.nodeType == "affiliation-item" ||
									o_propertiesRecord.nodeType == "widget-item" ||
                                    o_propertiesRecord.nodeType == "relation-grid" ||
                                    o_propertiesRecord.nodeType == "app-component") {

									if (position == "append") {
										b_allowed = true;
									}
								}
							}

							if (o_propertiesOver.nodeType == "content-root") {

								if (o_propertiesRecord.nodeType == "group") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "pd-group") {

									if (position == "append") {
										b_allowed = true;
									}
                                }
                                else if (o_propertiesRecord.nodeType == "app-component") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "uiLayout") {

									if (position == "append") {
										b_allowed = true;
									}
								}
							}
							else if (o_propertiesOver.nodeType == "tab-content") {

								if (o_propertiesRecord.nodeType == "group") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "pd-group") {

									if (position == "append") {
										b_allowed = true;
									}
                                }
                                else if (o_propertiesRecord.nodeType == "app-component") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "uiLayout") {

									if (position == "append") {
										b_allowed = true;
									}
								}
							}
							else if (o_propertiesOver.nodeType == "group") {

								if (o_propertiesRecord.nodeType == "group") {

									if (i_overRecord.getOwnerTree() == i_record.getOwnerTree()) {

										if (position == "after" || position == "before") {
											b_allowed = true;
										}
									}
								}
								else if (o_propertiesRecord.nodeType == "pd-group") {

									if (i_overRecord.getOwnerTree() == i_record.getOwnerTree()) {

										if (position == "after" || position == "before") {
											b_allowed = true;
										}
									}
								}
								else if (o_propertiesRecord.nodeType == "field" && !o_propertiesRecord.isHost) {
									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "pd-field") {
									if (position == "append") {
										b_allowed = true;
									}
								}
							}
							else if (o_propertiesOver.nodeType == "field") {
								if (position == "before" || position == "after") {
									if (o_propertiesRecord.nodeType == "field") {
										b_allowed = true;
									}
									else if (o_propertiesRecord.nodeType == "pd-field") {
										b_allowed = true;
									}
								}
							}
							else if (o_propertiesOver.nodeType == "pd-field") {
								if (position == "before" || position == "after") {
									if (o_propertiesRecord.nodeType == "field") {
										b_allowed = true;
									}
									else if (o_propertiesRecord.nodeType == "pd-field") {
										b_allowed = true;
									}
								}
							}
							else if (o_propertiesOver.nodeType == "uiLayout") {

								if (o_propertiesRecord.nodeType == "uiLayout") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "group") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "pd-group") {

									if (position == "append") {
										b_allowed = true;
									}
                                }
                                else if (o_propertiesRecord.nodeType == "app-component") {

									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "relation-grid") {
									if (position == "append") {
										b_allowed = true;
									}
								}
								else if (o_propertiesRecord.nodeType == "affiliation-item") {
									if (position == "append") {
										b_allowed = true;
									}
								}
							}

							else if (o_propertiesOver.nodeType == "relation-grid") {
								if (position == "before") {
									if (o_propertiesRecord.nodeType == "relation-grid") {
										b_allowed = true;
									}
								}
							}

							else if (o_propertiesOver.nodeType == "affiliation-item") {
								if (position == "before") {
									if (o_propertiesRecord.nodeType == "affiliation-item") {
										b_allowed = true;
									}
								}
							}

							else if (o_propertiesOver.nodeType == "widget-item") {
								if (position == "before") {
									if (o_propertiesRecord.nodeType == "widget-item") {
										b_allowed = true;
									}
								}
							}
							else if (o_propertiesRecord.nodeType == "app-component") {

								if (o_propertiesRecord.nodeType == "app-component") {

									if (position == "after" || position == "before") {
										b_allowed = true;
									}
								}
							}
						}
						return b_allowed;
					}
				}
			},
			listeners: {
				beforedrop: {
					fn: function (node, data, i_overModel, dropPosition, dropHandler, e) {

						var i_tree = i_overModel.getOwnerTree();
						var i_originTree = data.view.ownerGrid;

						if (data.view != i_tree.view) {

							var b_copy = true;

							var a_records = data.records.slice();

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

								var o_properties = i_record.get("properties");

								if (o_properties.nodeType == "field") {
									i_originTree.updateColumnsArray("remove", o_properties.name);
									b_copy = false;
								}
								else if (o_properties.nodeType == "pd-field") {
									i_originTree.updateColumnsArray("remove", o_properties.name);
									b_copy = false;
								}
								else if (o_properties.nodeType == "pd-group") {
									i_originTree.updateColumnsArray("remove", o_properties.name);
									b_copy = false;
								}
								else if (o_properties.nodeType == "relation-grid") {
									b_copy = false;
								}
								else if (o_properties.nodeType == "affiliation-item") {
									b_copy = false;
								}
								else if (o_properties.nodeType == "widget-item") {
									b_copy = false;
								}
							});

							if (b_copy) {
								data.records = [];
								data.copy = true;
								dropHandler.cancelDrop();
								i_self.addToLayout(a_records, i_overModel);
							}
						}
					}
				},
				drop: {
					fn: function(i_record, data, i_overModel) {

						var i_tree = i_overModel.getOwnerTree();

						var a_records = data.records.slice();

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

							var o_properties = i_record.get("properties");

							if (o_properties.nodeType == "field") {
								i_tree.updateColumnsArray("add", o_properties.name);
							}
							else if (o_properties.nodeType == "pd-field") {
								i_tree.updateColumnsArray("add", o_properties.name);
							}
							else if (o_properties.nodeType == "pd-group") {
								i_tree.updateColumnsArray("add", o_properties.name);
                            }
							else if (o_properties.nodeType == "relation-grid") {
								i_tree.updateColumnsArray("remove", "relation-grid" + o_properties.entityClass + "-" + o_properties.view);
							}
						});


						if (a_records.length == 1) {

							var i_view = i_tree.getView();
							i_view.getSelectionModel().select(a_records);
						}
					}
				}
			}
		};
	},

	createColumns: function() {

		var a_TreeColumns = [
			{
				xtype: "treecolumn",
				text: ip2.i18n("name"),
				flex: 2,
				sortable: true,
				dataIndex: "properties",
				renderer: function (value) {
					var s_value = value.name;
					return ip2.i18n(s_value, value.name);
				}
			},
			{
				text: ip2.i18n("title"),
				flex: 1,
				sortable: true,
				dataIndex: "title",
				renderer: function (value, i_cell, i_record) {

					var o_properties = i_record.get("properties") || {};

					var s_value = o_properties.title;
					return ip2.i18n(s_value, value);
				}
			}
		];

		return a_TreeColumns;
	},

	createStore: function() {

		var i_self = this;

		var o_entity = i_self.getEntity();
		var o_view = o_entity.ui.forms[i_self.getContext()] || o_entity.ui.forms.portfolio || {};
		var o_viewClone = Ext.clone(o_view);

		var a_groups = i_self.createGroups(o_viewClone);
		var a_relations = i_self.createRelations(o_viewClone);
		var a_widgets = i_self.createWidgets(o_viewClone);
		var a_affiliations = i_self.createAffiliations(o_viewClone);

		var a_viewTabs = Ext.Array.from(o_viewClone.tabs);

		var o_root = Ext.Array.findBy(a_viewTabs, function(o_tab) {
			return o_tab.contentRoot;
		}) || {
			properties: {
				nodeType: "content-root",
				name: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				title: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				layout: "anchor",
				bodyPadding: 20,
				defaults: {
					anchor: "100%",
					maxWidth: 800,
					labelWidth: 150
				}
			},
		};

		o_root = Ext.clone(o_root);

		delete o_root.itemId;
		delete o_root.index;
		delete o_root.contentRoot;

		var o_contentRoot = {
			itemId: "content-root",
			expanded: false,
			allowDrop: true,
			allowDrag: false,
			properties: Ext.apply({
				nodeType: "content-root",
				name: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				title: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				layout: "anchor",
				bodyPadding: 20,
				autpScroll: true,
				defaults: {
					anchor: "100%",
					maxWidth: 800,
					labelWidth: 150
				}
			}, o_root),
			children: []
		};

		var a_tabs = [];

		var a_temp = Ext.Array.from(o_viewClone.tabs);

		a_temp = Ext.Array.filter(a_temp, function(o_tab) {
			return !o_tab.contentRoot;
		});

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

			var o_tab;

			if (o_config.type != "app-component") {

				o_tab = {
					itemId: o_config.name,
					expanded: true,
					allowDrop: true,
					allowDrag: true,
					properties: Ext.apply({
						nodeType: "tab-content"
					}, o_config),
					children: []
				};
	
				var a_tabGroups = Ext.Array.filter(a_groups, function(o_group) {
					return o_group.properties.tabId == o_tab.itemId;
				});
	
				Ext.Array.each(a_tabGroups, function(o_group) {
					Ext.Array.remove(a_groups, o_group);
				});
	
				if (o_config.uiLayout) {
	
					Ext.apply(o_config, {
						layout: "fit"
					});
	
					o_tab.children = o_tab.children.concat([
						i_self.createLayoutNode(null, null, o_config.uiLayout, a_tabGroups, a_relations, a_widgets, a_affiliations)
					]);
				}
				else {
					o_tab.children = a_tabGroups;
				}
			}
			else {

                var s_itemId = o_config.itemId;

                o_tab = {
                    itemId: s_itemId,
                    expanded: false,
                    allowDrop: true,
                    allowDrag: true,
                    leaf: true,
                    iconCls: "pf-monitor",
                    properties: Ext.applyIf(o_config, {
                        nodeType: "app-component",
                        name: s_itemId
                    })
                };
            }
			
			a_tabs.push(o_tab);
		});

		a_tabs.unshift(o_contentRoot);

		var o_tabs = {
			itemId: "tabs-root",
			expanded: true,
			allowDrop: true,
			allowDrag: false,
			properties: {
				nodeType: "tabs-root",
				name: ip2.i18n({
					da: "Tabs",
					en: "Tabs"
				}),
			},
			children: a_tabs
		};

		if (!o_viewClone.uiLayout) {

			o_contentRoot.children = o_contentRoot.children.concat(a_groups);
			o_tabs.children = a_tabs.concat(a_relations).concat(a_affiliations).concat(a_widgets);
		}
		else {
			o_contentRoot.children = o_contentRoot.children.concat(
				[i_self.createLayoutNode(null, null, o_viewClone.uiLayout, a_groups, a_relations, a_widgets, a_affiliations)
			]);
		}

		if (o_contentRoot.children.length > 0) {
			o_contentRoot.expanded = true;
		}

		var i_store = Ext.create("Ext.data.TreeStore", {
			model: "Portfolio.designer.model.domainModelEntityFormDesignerTreeDataModel",
			folderSort: false,
			root: {
				expanded: true,
				allowDrop: true,
				allowDrag: false,
				children: [
					o_tabs
				],
				iconCls: "pf-window",
				properties: {
					nodeType: "form-root",
					name: ip2.i18n({
						da: "Form",
						en: "Form"
					})
				},
			}
		});

		return i_store;
	},

	createGroups: function (o_view) {

		var i_self = this;
		var i_designer = i_self.getDesigner();
		var o_model = i_designer.model;
		var a_entities = o_model.required;
		var a_groups = [];
		var i_entityManager = i_self.getEntityManager();
		var i_columnManager = i_entityManager.getColumnManager();

		Ext.Object.each(o_view.groups, function (s_group, o_group) {

			Ext.applyIf(o_group, {
				name: s_group
			});

			var o_config;
			

			var s_nodetype = "group";

			if (o_group.type == "app-component") {
				s_nodetype = "app-component";
				
				o_config = Ext.clone(o_group);
			}
			else {

				if (o_group.type == "collection" || o_group.type == "group") {
					s_nodetype = o_group.apperence == "group" ? "pd-group" : "group";
	
					if (s_nodetype == "pd-group") {
						i_self.updateColumnsArray("add", s_group);
					}
				}
	
				o_config = Ext.apply({}, {
					iconCls: s_nodetype == "pd-group" ? "pf-elements": "",
					leaf: (s_nodetype =="pd-group") ? true : false,
					expanded: (s_nodetype =="pd-group") ? true : false,
					allowDrop: (s_nodetype =="pd-group") ? false : true,
					allowDrag: o_group.extended ? false : true,
					sequence: o_group.sequence,
					properties: Ext.Object.merge({}, o_group, {
						nodeType: s_nodetype
					}),
					children: (s_nodetype =="pd-group") ? null : []
				});
			}

			a_groups.push(o_config);
		});

		Ext.applyIf(o_view, {
			items: {
				columns: []
			}
		});

		var a_items = Ext.isArray(o_view.items) ? o_view.items : o_view.items.columns;
		var a_columns = Ext.Array.from(a_items);

		var o_entity = i_self.getEntity();

		var a_entityColumns = o_entity.columns.slice() || [];

		Ext.Array.each(a_entityColumns, function (o_entityColumn) {

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

				if (o_entityColumn.name == o_column.name) {

					o_column = Ext.applyIf(o_column, o_entityColumn);

					var a_props = Ext.Object.getKeys(o_column);

					Ext.Array.each(a_props, function (s_key) {

						if (s_key != "sequence") {

							if (Ext.isEmpty(o_column[s_key], false) || o_column[s_key] == 0) {
								delete o_column[s_key];
							}
						}
					});

					if (o_column.type) {
						o_column.type = o_column.type.split("(")[0];
					}
					else {
						o_column.type = "varchar";
					}

					return false;
				}
			});
		});

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

			var o_field;
			var s_name = "";

			var s_nodetype = "field";

			if (o_column.type == "property" ) {
				s_nodetype = "pd-field";
			}

			o_field = Ext.apply({}, {
				itemId: o_column.from ? o_column.name : o_column.name,
				leaf: true,
				allowDrop: false,
				allowDrag: o_column.extended ? false : true,
				iconCls: s_nodetype == "pd-field" ? "pf-element": "",
				properties: Ext.apply(o_column, {
					name: o_column.name,
					nodeType: s_nodetype,
					extended: o_column.extended,
					entityClass: o_column.from ? o_column.from : o_entity.name
				})
			});

			var o_properties = o_field.properties;

			if (o_column.from) {

				if (o_column.name.indexOf(".") > -1) {
					s_name = o_column.name.split(".").pop();
				}
				else if (o_column.name.indexOf("-") > -1) {
					s_name = o_column.name.split("-").pop();
				}
				else if (o_column.name.indexOf("_") > -1) {
					var a_split = o_column.name.split("_");
					if (a_split.length < 2) {
						s_name = a_split.join("_");
					}
					else {
						a_split.shift();
						s_name = a_split.join("_");
					}
				}
				
				if (!o_field.iconCls) {
					o_field.iconCls = "ip2-designer-relation-field";
				}
				

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

				if (o_entity) {

					var o_entityColumn = Ext.Array.findBy(o_entity.columns, function (o_value) {
						return o_value.name == s_name;
					});

					if (o_entityColumn) {
						if (o_properties.hasOwnProperty("fieldLabel")) {
							if (o_properties.fieldLabel != o_properties.title) {
								o_field.properties.title = o_properties.fieldLabel;
							}
						}
						else {
							o_field.properties.title = o_entityColumn.title || o_entityColumn.name;
						}
					}
				}
			}
			else {
				if (o_field.leaf) {

					if (!o_field.iconCls) {
						o_field.iconCls = o_properties.relation ? "ip2-designer-relation-field" : "ip2-designer-field";
					}
					
					var i_entityColumn = i_columnManager.columnGrid.store.getById(o_column.name);

					if (i_entityColumn) {

						if (o_properties.hasOwnProperty("fieldLabel")) {

							if (o_properties.fieldLabel != o_properties.title) {

								o_field.properties.title = o_properties.fieldLabel;
							}
						}
						else {
							o_field.properties.title = i_entityColumn.get("title") || i_entityColumn.get("name");
						}
					}
					else {
						o_field.properties.title = o_properties.name;
					}
				}
			}

			var s_identifier = o_properties.relation ? "relation-field-" + o_column.name : o_column.name;

			if (o_column.from) {
				s_identifier = o_column.name;
			}

			if (o_column.group) {

				i_self.updateColumnsArray("add", s_identifier);

				var o_found = Ext.Array.findBy(a_groups, function (o_group) {
					return o_group.properties.name == o_column.group;
				});

				if (o_found) {
					o_found.children.push(o_field);
				}
			}
		});

		Ext.Array.each(a_groups, function(o_group) {
			
			if (o_group.properties.nodeType != "pd-group") {
				if (o_group.children.length > 0) {
					o_group.expanded = true;
				}
			}
		});

		return a_groups;
	},

	createRelations: function (o_view) {

		var i_self = this;

		var a_relations = [];

		Ext.Array.each(o_view.relation, function (o_value) {

			var s_value = "relation-grid-" + o_value.entity + "-" + o_value.view;

			var o_config = Ext.apply({}, {
				itemId: s_value,
				leaf: true,
				allowDrop: false,
				allowDrag:  o_value.extended ? false : true,
				sequence: o_value.sequence || -1,
				properties: {
					name: o_value.entity + " - " + o_value.view,
					nodeType: "relation-grid",
					title: o_value.title || o_value.entity,
					view: o_value.view,
					index: o_value.index || 0,
					entityClass: o_value.entity,
					window: o_value.window || {}
				},
				children: []
			});

			i_self.updateColumnsArray("add", s_value);

			a_relations.push(o_config);
		});

		return a_relations;
	},

	createAffiliations: function (o_view) {

		var i_self = this;

		var a_affiliations = [];

		Ext.Array.each(o_view.affiliations, function (o_value) {

			var o_config = {
				itemId: "affiliation-" + o_value.name,
				iconCls: "ip2-designer-affiliation",
				leaf: true,
				allowDrop: false,
				allowDrag:  o_value.extended ? false : true,
				sequence: o_value.sequence || -1,
				properties: {
					name: o_value.name,
					url: o_value.url,
					nodeType: "affiliation-item",
					index: o_value.index || 0,
					title: o_value.title,
					component: o_value.component || {}
				},
				children: []
			};

			a_affiliations.push(o_config);

			i_self.updateColumnsArray("add", "affiliation-" + o_value.name);

		});

		return a_affiliations;
	},

	createWidgets: function(o_view) {

		var i_self = this;

		var a_widgets = [];

		Ext.Object.each(o_view.widgets, function (s_key, o_value) {

			var o_config = {
				itemId: "widget-" + s_key,
				leaf: true,
				allowDrop: false,
				allowDrag:  o_value.extended ? false : true,
				sequence: o_value.sequence,
				properties: {
					name: o_value.name || s_key,
					path: o_value.path,
					nodeType: "widget-item",
					width: 0,
					height: 0,
					index: o_value.index || 0,
					title: o_value.title
				},
				children: []
			};

			a_widgets.push(o_config);

			i_self.updateColumnsArray("add", "widget-" + s_key);
		});

		return a_widgets;
	},

	createLayoutNode: function (s_type, s_region, o_inital, a_groups, a_relations, a_widgets, a_affiliations) {

		var i_self = this;

		if (o_inital && !Ext.isObject(o_inital)) {

			var o_found = Ext.Array.findBy(a_groups, function (o_group) {
				return o_group.properties.name == o_inital;
			});

			if (!o_found) {
				o_found = Ext.Array.findBy(a_relations, function (o_relation) {
					return o_relation.itemId == o_inital;
				});
			}

			if (!o_found) {
				o_found = Ext.Array.findBy(a_widgets, function (o_widget) {
					return o_widget.properties.name == o_inital;
				});
			}

			if (!o_found) {
				o_found = Ext.Array.findBy(a_affiliations, function (o_affiliation) {
					return o_affiliation.properties.name == o_inital;
				});
			}

			return o_found || {
				itemId: "layout-item-" + o_inital,
				text: o_inital,
				leaf: true,
				allowDrag: false,
				allowDrop: false,
				properties: {
					type: o_inital,
					name: o_inital,
					nodeType: "layoutItem"
				},
				children: []
			};
		}

		o_inital = o_inital || {};

		var o_properties = Ext.applyIf(o_inital, {
			title: "",
			type: s_type,
			name: s_type,
			region: "",
			split: true,
			flex: 1,
			collapsible: false,
			collapsed: false,
			defaults: {},
			border: false,
			bodyPadding: s_type == "anchor" ? 10 : 0,
			width: 0,
			height: 0,
			minWidth: 0,
			maxWidth: 0,
			minHeight: 0,
			maxHeight: 0,
			nodeType: "uiLayout"
		});

		s_type = o_properties.type;
		s_region = o_properties.region || s_region;

		var a_children = o_properties.items || [];

		var a_result = [];

		Ext.Array.each(a_children, function (o_child) {
			var o_layout = i_self.createLayoutNode(null, null, o_child, a_groups, a_relations, a_widgets, a_affiliations);
			a_result.push(o_layout);
		});

		var o_config = {
			text: s_type,
			leaf: false,
			expanded: false,
			allowDrag: true,
			allowDrop: false,
			properties: o_properties,
			children: a_result
		};

		if (s_type == "anchor") {
			o_config.properties.autoScroll = true;
		}

		if (s_region) {
			o_config.properties.region = s_region;
			o_config.properties.name = s_type + " ( <strong>" + s_region + "</strong> )";
		}

		return o_config;
	},

	doSave: function (o_entity) {

		var i_self = this;

		o_entity = o_entity || i_self.getEntity();

		var o_view = o_entity.ui.forms[i_self.getContext()] || o_entity.ui.forms.portfolio || {};

		var i_root = i_self.getRootNode();

		var i_tabs = i_root.findChild("itemId", "tabs-root", true);
		var i_content = i_root.findChild("itemId", "content-root", true);

		var a_definitions = i_self.getDefinitions();

		var o_form = {
			columns: [],
			items: [],
			layout: o_view.layout || {},
			groups: {},
			relation: [],
			affiliations: [],
			widgets: {},
            tabs: []
		};

		var a_tabpanels = [];
		var a_groups = [];
		var a_uiLayouts = [];
		var a_relations = [];
		var a_widgets = [];
        var a_affiliations = [];

		i_content.cascadeBy(function(i_record) {

			var o_properties = i_record.get("properties") || {};

			if (o_properties.nodeType == "group") {
				
				a_groups.push(i_record);

				delete o_properties.tabId;
			}

			if (o_properties.nodeType == "pd-group") {

				a_groups.push(i_record);
				
				delete o_properties.tabId;	
            }
            
            if (o_properties.nodeType == "app-component") {
                a_groups.push(i_record);
            }
		});

		i_content.cascadeBy(function (i_record) {

			var o_properties = i_record.get("properties") || {};

			if (o_properties.nodeType == "uiLayout") {

				a_uiLayouts.push(i_record);

			}
		});

		a_tabpanels.push(i_content);

		Ext.Array.each(i_tabs.childNodes, function (i_tab) {

			var o_properties = i_tab.get("properties") || {};

			if (o_properties.nodeType == "tab-content") {

				var s_tabId = i_tab.get("itemId");
				var a_tabLayout = [];

				i_tab.cascadeBy(function(i_record) {

					var o_properties = i_record.get("properties") || {};
				
					if (o_properties.nodeType == "group") {

						o_properties.tabId = s_tabId;

						a_groups.push(i_record);
					}

					if (o_properties.nodeType == "pd-group") {

						o_properties.tabId = s_tabId;

						a_groups.push(i_record);

                    }
                    
                    if (o_properties.nodeType == "app-component") {

                        o_properties.tabId = s_tabId;
						a_groups.push(i_record);

					}
				});
		
				i_tab.cascadeBy(function (i_record) {
		
					var o_properties = i_record.get("properties") || {};
		
					if (o_properties.nodeType == "uiLayout") {

						a_tabLayout.push(i_record);
					}
				});

				if (a_tabLayout.length > 0) {
					var o_uiLayout = i_self.getLayoutNode(a_tabLayout[0]);
					o_properties.uiLayout = o_uiLayout;
				}

				a_tabpanels.push(i_tab);
            }
            else if (o_properties.nodeType == "app-component") {
                a_tabpanels.push(i_tab);
            }
		});

		i_tabs.cascadeBy(function (i_record) {

			var o_properties = i_record.get("properties") || {};

			if (o_properties.nodeType == "relation-grid") {

				a_relations.push(i_record);

			}
		});

		i_tabs.cascadeBy(function (i_record) {

			var o_properties = i_record.get("properties") || {};

			if (o_properties.nodeType == "affiliation-item") {

				a_affiliations.push(i_record);

			}
		});

		i_tabs.cascadeBy(function (i_record) {

			var o_properties = i_record.get("properties") || {};

			if (o_properties.nodeType == "widget-item") {

				a_widgets.push(i_record);

			}
		});

		Ext.Array.each(a_tabpanels, function(i_tab, n_index) {

			var o_properties = i_tab.get("properties");

			if (!o_properties.extended) {
                
                var o_values;

                if (o_properties.nodeType != "app-component") {

                    o_values = Ext.apply({}, {
                        itemId: i_tab.get("itemId"),
                        name: o_properties.name,
                        title: o_properties.title,
                        index: 0,
                        defaults: o_properties.defaults,
                        bodyPadding: o_properties.bodyPadding,
                        layout: o_properties.layout || "fit",
                        contentRoot: o_properties.nodeType == "content-root",
                        uiLayout: o_properties.uiLayout,
                        sequence: n_index,
                        autoScroll: o_properties.autoScroll || false
                    });
                }
                else {

                    var o_clone = Ext.clone(o_properties);

                    o_values = Ext.apply(o_clone, {
                        contentRoot: false,
                        type: o_properties.nodeType,
                        sequence: n_index
                    });

                    delete o_values.nodeType;
                }

				o_form.tabs.push(o_values);
			}

		});

		Ext.Array.each(a_groups, function(i_group, n_index) {

			var o_properties = i_group.get("properties") || {};

			var o_group;

			if (!o_properties.extended) {

				o_group = Ext.Object.merge(Ext.clone(o_properties), {
					sequence: n_index
				});

				if (o_group.nodeType == "pd-group") {

					o_group = {
						title: o_group.title,
						name: o_group.name,
						sequence: o_group.sequence,
						tabId: o_group.tabId,
						type: o_group.type,
						nodeType: o_group.nodeType,
						cms_dmd_collection_id :o_group.cms_dmd_collection_id,
						label: o_group.label,
						apperence: o_group.apperence
					};
                }
                
                if (o_group.nodeType == "app-component") {

					Ext.apply(o_group, {
                        type: o_group.nodeType
                    });
				}

                delete o_group.nodeType;
                
                var a_children = i_group.childNodes || [];

				Ext.Array.each(a_children, function (i_record, n_index) {

					var o_properties = i_record.get("properties") || {};

					var o_definition = Ext.Array.findBy(a_definitions, function(o_def){
						return o_def.name == o_properties.name;
					});

					if (o_properties.nodeType == "field") {

						var o_field = Ext.apply(Ext.clone(o_properties), {
							sequence: n_index,
							group: o_group.name
						});

						delete o_field.nodeType;
						delete o_field.fullname;
						delete o_field.entityClass;

						if (!o_properties.extended) {

							if (!o_definition || !o_definition.active) {
								o_form.columns.push({
									name: o_field.name
								});
							}
							
							o_form.items.push(o_field);
						}
					}

					if (o_properties.nodeType == "pd-field") {

						var o_field = Ext.apply(Ext.clone(o_properties), {
							sequence: n_index,
							group: o_group.name
						});

						delete o_field.nodeType;
						delete o_field.fullname;
						delete o_field.entityClass;

						if (!o_properties.extended) {
							o_form.items.push(o_field);
						}
					}
				});

				o_form.groups[o_group.name] = o_group;
			}
			else {

				var a_children = i_group.childNodes || [];

				o_group = {
					name: o_properties.name,
					sequence: n_index
				};

				Ext.Array.each(a_children, function (i_record, n_index) {

					var o_properties = i_record.get("properties") || {};

					if (!o_properties.extended) {

						var o_definition = Ext.Array.findBy(a_definitions, function(o_def){
							return o_def.name == o_properties.name;
						});
	
						if (o_properties.nodeType == "field") {
	
							var o_field = Ext.apply(Ext.clone(o_properties), {
								sequence: n_index,
								group: o_group.name
							});
	
							delete o_field.nodeType;
							delete o_field.fullname;
							delete o_field.entityClass;
	
							if (!o_properties.extended) {
	
								if (!o_definition || !o_definition.active) {
									o_form.columns.push({
										name: o_field.name
									});
								}
								
								o_form.items.push(o_field);
							}
						}
	
						if (o_properties.nodeType == "pd-field") {
	
							var o_field = Ext.apply(Ext.clone(o_properties), {
								sequence: n_index,
								group: o_group.name
							});
	
							delete o_field.nodeType;
							delete o_field.fullname;
							delete o_field.entityClass;
	
							if (!o_properties.extended) {
								o_form.items.push(o_field);
							}
						}
					}
				});
			}

		});

		Ext.Array.each(a_relations, function(i_relation, n_index) {

			var o_properties = i_relation.get("properties") || {};

			if (!o_properties.extended) {

				var o_values = Ext.apply({}, {
					entity: o_properties.entityClass,
					title: o_properties.title || "",
					view: o_properties.view,
					index: o_properties.index || 0,
					window: o_properties.window || {}
				});
	
				o_form.relation.push(o_values);
			}
			
		});

		Ext.Array.each(a_affiliations, function(i_affiliation, n_index) {

			var o_properties = i_affiliation.get("properties");

			if (!o_properties.extended) {

				var o_values = Ext.apply({}, {
					url: o_properties.url,
					name: o_properties.name,
					title: o_properties.title,
					index: o_properties.index || 0,
					component: o_properties.component
				});

				o_form.affiliations.push(o_values);
			}
		});

		Ext.Array.each(a_widgets, function (i_widget, n_index) {

			var o_properties = i_widget.get("properties");

			if (!o_properties.extended) {

				var o_values = Ext.apply({}, {
					path: o_properties.path,
					name: o_properties.name,
					title: o_properties.title,
					width: o_properties.width || null,
					height: o_properties.height || null,
					layout: o_properties.layout || "fit",
					autoScroll: o_properties.autoScroll || false,
					index: o_properties.index || n_index,
					sequence: o_properties.index || n_index
				});

				o_form.widgets[o_properties.name] = o_values;
			}
		});

		if (a_uiLayouts.length > 0) {
			var o_uiLayout = i_self.getLayoutNode(a_uiLayouts[0]);
			o_form.uiLayout = o_uiLayout;
		}

		return o_form;
	},

	getLayoutNode: function (i_parent) {

		var i_self = this;

		var a_children = i_parent.childNodes || [];
		var value;

		var o_properties = Ext.clone(i_parent.get("properties"));
		var a_items = [];

		Ext.Array.each(a_children, function (i_child) {

			var o_result = i_self.getLayoutNode(i_child);

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

			a_items = a_items.concat(a_values);

			a_items = Ext.Array.filter(a_items, function(value) {
				return value;
			});
		});
		
		if (o_properties.nodeType == "collection") {
			value = a_items;
		}
		else if (o_properties.nodeType == "layoutItem") {
			value = o_properties.type;
			if (o_properties.relationId && o_properties.view) {
				value = o_properties.relationId;
			}
		}
		else {
			o_properties.items = a_items;

			value = o_properties;
		}

		if (o_properties.nodeType == "group") {
			value = o_properties.name;
        }
        else if (o_properties.nodeType == "app-component") {
			value = o_properties.name;
		}
		else if (o_properties.nodeType == "pd-group") {
			value = o_properties.name;
		}
		else if (o_properties.nodeType == "relation-grid") {
			value = "relation-grid-" + (o_properties.view ?
											o_properties.entityClass + "-" + o_properties.view :
											o_properties.entityClass + "-" + "portfolio");
		}
		else if (o_properties.nodeType == "affiliation-item") {
			value = o_properties.name;
		}
		else if (o_properties.nodeType == "widget-item") {
			value = o_properties.name;
		}

		return value;
	},

	addListeners: function () {

		var i_self = this;

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

					var i_store = i_treepanel.getStore();
					var a_records = i_store.getRange(0);

					Ext.Array.each(a_records, function (i_record) {
						i_record.commit();
					});
				},
				buffer: 10
			},
			updateAffiliation: {
				fn: function (i_tree, o_data) {

					var i_root = i_tree.getRootNode();
					var i_node = i_root.findChild("itemId", "affiliation-" + o_data.name, true);

					if (i_node) {

						var o_properties = i_node.get("properties");
						Ext.apply(o_properties, o_data);
						i_node.set("properties", o_properties);
						i_node.commit();
					}
				}
			},
			updateColumn: {
				fn: function(s_old, s_new) {

					var i_self = this;
					var i_root = i_self.getRootNode();

					var i_node = i_root.findChild("itemId", s_old, true);

					if (i_node) {

						var o_properties = i_node.get("properties");

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

						i_node.set({
							itemId: s_new,
							properties: o_properties
						});

						i_node.commit();

						i_self.updateColumnsArray("remove", s_old);
						i_self.updateColumnsArray("add", s_new);

					}
				}
			},
			removeColumn: {
				fn: function(s_column) {

					var i_self = this;
					i_self.removeColumn(s_column);
				}
			},
			removeRelation: {
				fn: function (i_treepanel, s_entity) {

					var i_self = this;

					i_self.removeRelation(s_entity);

					return true;
				}
			},
			removeAffiliation: {
				fn: function (i_treepanel, s_name) {

					var i_self = this;

					i_self.removeAffiliation(s_name);

					return true;
				}
			},
			itemcontextmenu: {
				fn: function (i_view, i_record, i_item, n_index, i_event) {

					var o_properties = i_record.get("properties");
					var i_parentNode = i_record.parentNode || i_record;

					i_event.stopEvent();

					var a_coords = i_event.getXY();

					var a_items = [];

					if (!i_record.isRoot()) {

						if (o_properties.nodeType != "tabs-root" && o_properties.nodeType != "content-root") {

							if (!o_properties.extended) {

								a_items.push({
									xtype: "menuitem",
									text: ip2.i18n({
										da: "Slet",
										en: "Delete"
									}),
									itemId: "delete",
									iconCls: "pf-delete",
									handler: function () {
										i_parentNode.collapse();
		
										var o_config = i_self.removeNode(i_record, true);
		
										i_record.remove(false);
										i_parentNode.expand();
		
										i_self.fireEvent("syncTrees", o_config);
									}
								});
							}
							
						}
						else {
							if (o_properties.nodeType == "tabs-root") {

                                var i_addmenu = Ext.widget("menuitem", {
                                    text: ip2.i18n({
										da: "Tilføj",
										en: "Add"
                                    }),
                                    menu: {
                                        items: [{
                                            text: ip2.i18n({
                                                da: "Tab",
                                                en: "Tab"
                                            }),
                                            itemId: "tab-add",
                                            iconCls: "pf-add",
                                            handler: function () {
                                                i_record.collapse();
        
                                                var s_itemId = Ext.id(null, "tab-");
        
                                                var o_tab = {
                                                    itemId: s_itemId,
                                                    expanded: false,
                                                    allowDrop: true,
                                                    allowDrag: true,
                                                    properties: {
                                                        nodeType: "tab-content",
                                                        name: s_itemId,
                                                        title: ip2.i18n({
                                                            da: "Tab",
                                                            en: "Tab"
                                                        }),
                                                        layout: "anchor",
                                                        autoScroll: true,
                                                        bodyPadding: 20,
                                                        defaults: {
                                                            anchor: "100%",
                                                            maxWidth: 800,
                                                            labelWidth: 150
                                                        }
                                                    },
                                                    children: []
                                                };
                
                                                i_record.appendChild(o_tab);
                                                i_record.expand();
                                            }
                                        },
                                        {
                                            xtype: "menuitem",
                                            text: ip2.i18n({
                                                da: "App",
                                                en: "App"
                                            }),
                                            itemId: "app-add",
                                            iconCls: "pf-add",
                                            handler: function () {
        
                                                var i_paths = Ext.widget("acetextarea", {
                                                    xtype: "acetextarea",
                                                    fieldLabel: ip2.i18n({
                                                        da: "Sti",
                                                        en: "Path"
                                                    }),
                                                    hideLabel: false,
                                                    name: "path",
                                                    mode: "json",
                                                    asJson: true
                                                });
        
                                                var i_config = Ext.widget("acetextarea", {
                                                    xtype: "acetextarea",
                                                    fieldLabel: ip2.i18n({
                                                        da: "Config",
                                                        en: "Config"
                                                    }),
                                                    hideLabel: false,
                                                    name: "config",
                                                    mode: "json",
                                                    asJson: true
                                                });
        
                                                var i_formpanel = Ext.widget("form", {
                                                    xtype: "form",
                                                    layout: "anchor",
                                                    bodyPadding: 10,
                                                    defaults: {
                                                        anchor: "100%"
                                                    },
                                                    items: [
                                                        {
                                                            xtype: "textfield",
															fieldLabel: "Main",
															regex: new RegExp("^\\w+(?:\\.\\w+)*$"),
                                                            name: "main"
                                                        },
                                                        i_paths,
                                                        i_config,
                                                        {
                                                            xtype: "fieldset",
                                                            title: "Events",
                                                            collapsible: true,
                                                            collapsed: false,
                                                            layout: "anchor",
                                                            defaults: {
                                                                anchor: "100%"
                                                            },
                                                            items: [
                                                                {
                                                                    xtype: "textfield",
                                                                    fieldLabel: "Ready",
                                                                    name: "readyEvent",
                                                                    emptyText: "entityReady"
                                                                },
                                                                {
                                                                    xtype: "textfield",
                                                                    fieldLabel: "Save",
                                                                    name: "saveEvent",
                                                                    emptyText: "entitySave"
                                                                },
                                                                {
                                                                    xtype: "textfield",
                                                                    fieldLabel: "Complete",
                                                                    name: "completeEvent",
                                                                    emptyText: "saveComplete"
                                                                }
                                                            ]
                                                        }
                                                    ]
                                                });
        
                                                var i_window = Ext.widget("window", {
                                                    title: ip2.i18n({
                                                        da: "Tilføj app",
                                                        en: "Add app"
                                                    }),
                                                    layout: "fit",
                                                    modal: true,
                                                    width: 600,
                                                    items: [
                                                        i_formpanel
                                                    ]
                                                });

                                                var i_toolbar = Ext.widget("toolbar", {
                                                    dock: "bottom",
                                                    ui: "footer",
                                                    items: [
                                                        "->",
                                                        {
                                                            xtype: "button",
                                                            text: ip2.i18n({
                                                                da: "Anuller",
                                                                en: "Cancel"
                                                            }),
                                                            handler: function() {
                                                                i_window.close();
                                                            }
                                                        },
                                                        {
                                                            xtype: "button",
                                                            ui: "primary-button",
                                                            text: ip2.i18n({
                                                                da: "Ok",
                                                                en: "Ok"
                                                            }),
                                                            handler: function() {
                                                                i_record.collapse();

                                                                var o_values = i_formpanel.getValues(false, false, false, true);

                                                                var s_itemId = Ext.id(null, "app-");

                                                                var o_app = {
                                                                    itemId: s_itemId,
                                                                    expanded: false,
                                                                    allowDrop: true,
                                                                    allowDrag: true,
                                                                    leaf: true,
                                                                    iconCls: "pf-monitor",
                                                                    properties: Ext.applyIf(o_values, {
                                                                        nodeType: "app-component",
                                                                        name: s_itemId
                                                                    })
                                                                };
                                
                                                                i_record.appendChild(o_app);
                                                                i_record.expand();

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

                                                i_window.addDocked(i_toolbar);
        
                                                i_window.show();
                                            }
                                        }]
                                    }
                                });

                                a_items.push(i_addmenu);
							}
						}
					}

					if (a_items.length > 0) {
						var i_menu = Ext.widget("menu", {
							items: a_items
						});

						i_menu.showAt([a_coords[0], a_coords[1]]);
					}
				}
			},
			collectionchange: {
				fn: function(new_form, old_form) {

					var b_start = Ext.isEmpty(old_form);

					old_form = old_form || new_form;

					var o_saved = i_self.doSave();
					var o_entity = i_self.getEntity();
					var a_collections = i_self.getFormCollections();

					var o_view = o_entity.ui.forms[i_self.getContext()] || {
						layouts: []
					};

					var a_layouts = Ext.Array.from(o_view.layouts);

					var o_next =  Ext.Array.findBy(a_collections, function(o_definition) {
						return (o_definition.id == new_form || o_definition.name == new_form);
					});

					if (!o_next) {
						return false;
					}

					var n_current = -1;

					var o_current = Ext.Array.findBy(a_layouts, function(o_config, n_index) {
						var b_current = o_config.fcid == old_form;

						if (b_current) {
							n_current = n_index;
						}
						return b_current;
					}) || {};

					if (!b_start) {
						Ext.apply(o_current, o_saved);

						if (n_current > -1) {
							a_layouts[n_current] = o_current;
						}
						else {

							Ext.apply(o_current, {
								fcid: old_form
							});

							a_layouts.push(o_current);
						}
					}
					
					Ext.apply(o_view, {
						layouts: a_layouts
					});

					var i_root = i_self.getRootNode();
					
					var a_remove = [];

					var i_tabs = i_root.findChild("itemId", "tabs-root", true);

					var i_content = i_root.findChild("itemId", "content-root", true);

					i_content.collapse();

					i_root.collapse();
					i_tabs.collapse();

					Ext.Array.each(i_tabs.childNodes, function (i_tab) {

						var o_properties = i_tab.get("properties") || {};
			
						if (o_properties.nodeType == "tab-content") {

							a_remove.push(i_tab);
						}
					});

					Ext.Array.each(i_content.childNodes, function (i_child) {
						a_remove.push(i_child);
					});

					Ext.Array.each(a_remove, function(i_record) {
						i_self.removeNode(i_record);
						i_record.remove(false);
					});

					i_tabs.remove(false);

					o_current = Ext.Array.findBy(a_layouts, function(o_config, n_index) {
						return o_config.fcid == new_form;
					}) || {};
					

					var o_collection = Ext.Array.findBy(a_collections, function(o_definition) {
						return (o_definition.id == new_form || o_definition.name == new_form);
					});

					var a_extend = Ext.Array.from(o_collection.extend);

					var o_merged = {};

					if (a_extend.length) {

						var a_recursive = Portfolio.pd.util.Handler.getExtendedFormCollection(a_extend, a_collections);

						a_recursive.reverse();

						Ext.Array.each(a_recursive, function(o_definition) {

							var o_layout = Ext.Array.findBy(a_layouts, function(o_layout) {
								return (o_definition.id == o_layout.fcid || o_definition.name == o_layout.fcid);
							});

							if (o_layout) {

								var o_layoutClone = Ext.clone(o_layout);
								
								Ext.Object.each(o_layoutClone, function(s_key, value) {
									var temp;
									if (Ext.isArray(value)) {

										temp = Ext.clone(Ext.Array.from(o_merged[s_key]));

										var a_merged = Ext.Array.merge(temp, Ext.Array.clone(value));

										var a_searched = [];

										var a_filtered = Ext.Array.filter(a_merged, function(value) {

											var b_found = false;
											var s_search = value;

											if (Ext.isObject(value)) {

												if (value.type) {
													switch(value.type) {
														case "property":
															s_search = value.name;
															break;
														case "collection":
														case "group":
															s_search = value.itemId;
															break;
														default:
															s_search = value.itemId || value.name;
															break;
													}
												}
												else {
													s_search = value.itemId || value.name;
												}
											}

											b_found = a_searched.indexOf(s_search) > -1;

											if (!b_found) {
												a_searched.push(s_search);
											}

											return !b_found;
										});
										
										o_merged[s_key] = a_filtered;
									}
									if (Ext.isObject(value)) {
										temp = Ext.clone(o_merged[s_key]) || {};
										o_merged[s_key] = Ext.Object.merge(temp, Ext.clone(value));
									}
								});
		
								Ext.Object.mergeIf(o_merged, o_layout);
							}
						});

						i_self.markExtended(o_merged);
					}

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

						
						Ext.Object.each(o_current, function(s_key, value) {
							var temp;
							if (Ext.isArray(value)) {

								temp = Ext.Array.clone(Ext.Array.from(o_merged[s_key]));

								var a_merged = Ext.Array.merge(temp, Ext.Array.clone(value));

								var a_searched = [];

								var a_filtered = Ext.Array.filter(a_merged, function(value) {

									var b_found = false;
									var s_search = value;

									if (Ext.isObject(value)) {

										if (value.type) {
											switch(value.type) {
												case "property":
													s_search = value.name;
													break;
												case "collection":
												case "group":
													s_search = value.itemId;
													break;
												default:
													s_search = value.itemId || value.name;
													break;
											}
										}
										else {
											s_search = value.itemId || value.name;
										}
									}

									b_found = a_searched.indexOf(s_search) > -1;

									if (!b_found) {
										a_searched.push(s_search);
									}

									return !b_found;
								});

								o_current[s_key] = a_filtered;
							}
							if (Ext.isObject(value)) {
								temp = Ext.clone(o_merged[s_key]) || {};
								o_current[s_key] = Ext.Object.merge(temp, Ext.clone(value));
							}
						});

						Ext.Object.mergeIf(o_current, o_merged);
						
					}
					else{
						o_current = Ext.Object.merge(o_current, o_merged);

						if (Ext.Object.isEmpty(o_current)) {
							o_current = Ext.clone(o_view);
						}
					}

					var o_tabs = i_self.createFormLayout(o_current);

					i_root.appendChild(o_tabs);
					i_root.expand();

				}
			},
			syncup: {
				fn: function() {
					var o_keys = i_self.getKeys();
					return o_keys;
				}
			}
		});
	},

	removeNode: function(i_node, b_change) {

		var i_self = this;
		var a_fields = i_self.removeFields(i_node);
		var a_grids = i_self.removeRelationGrids(i_node);
		var a_widgets = i_self.removeWidgets(i_node);
		var a_affiliations = i_self.removeAffiliations(i_node);
		var a_definitions =  i_self.getDefinitions();

		var  i_pd;

		if (b_change) {

			i_pd = Ext.Array.findBy(a_fields, function(o_properties) {

				var b_found = o_properties.nodeType == "pd-field" || o_properties.nodeType == "pd-group";

				if (!b_found) {

					b_found = Ext.Array.findBy(a_definitions, function(o_def) {
						return o_def.name == o_properties.name;
					});
				}

				if (b_found) {
					o_properties.nodeType = o_properties.nodeType == "field" ? "pd-field" : "pd-group";
				}

				return b_found;
			});

			a_fields = Ext.Array.filter(a_fields, function(o_properties) {
				return o_properties.nodeType == "pd-field" || o_properties.nodeType == "pd-group";
			});
		}

		return {
			fields: a_fields,
			grids: a_grids,
			widget: a_widgets,
			a_affiliations: a_affiliations,
			pd: i_pd ? true : false
		};
	},

	removeFields: function(i_node) {

		var i_self = this;
		var a_removed = [];

		var a_children = Ext.Array.from(i_node.childNodes);

		Ext.Array.each(a_children, function (i_child) {
			a_removed = a_removed.concat(i_self.removeFields(i_child));
		});

		var o_properties = i_node.get("properties");

		switch(o_properties.nodeType) {
			case "field":
				if (o_properties.relation) {
					i_self.updateColumnsArray("remove", "relation-field-" + o_properties.name);
				}
				else {
					i_self.updateColumnsArray("remove", o_properties.name);
					a_removed.push(o_properties);
				}
				break;
			case "pd-field":
				i_self.updateColumnsArray("remove", o_properties.name);
				a_removed.push(o_properties);
				break;
			case "pd-group":
				i_self.updateColumnsArray("remove", o_properties.name);
				a_removed.push(o_properties);
				break;
		}
		return a_removed;
	},

	removeRelationGrids: function (i_node) {

		var i_self = this;
		var a_removed = [];

		var a_children = i_node.childNodes || [];

		Ext.Array.each(a_children, function (i_child) {
			a_removed = a_removed.concat(i_self.removeRelationGrids(i_child));
		});

		var o_properties = i_node.get("properties");

		if (o_properties.nodeType == "relation-grid") {

			i_self.updateColumnsArray("remove", "relation-grid-" + o_properties.name + "-" + o_properties.view);
			a_removed.push(o_properties);
		}

		return a_removed;
	},

	removeWidgets: function (i_node) {

		var i_self = this;
		var a_removed = [];

		var a_children = i_node.childNodes || [];

		Ext.Array.each(a_children, function (i_child) {
			a_removed = a_removed.concat(i_self.removeWidgets(i_child));
		});

		var o_properties = i_node.get("properties");

		if (o_properties.nodeType == "widget-item") {

			i_self.updateColumnsArray("remove", i_node.itemId);
			a_removed.push(o_properties);
		}

		return a_removed;
	},

	removeAffiliations: function (i_node) {

		var i_self = this;
		var a_removed = [];

		var a_children = i_node.childNodes || [];

		Ext.Array.each(a_children, function (i_child) {
			a_removed = a_removed.concat(i_self.removeAffiliation(i_child));
		});

		var o_properties = i_node.get("properties");

		if (o_properties.nodeType == "affiliation-item") {

			i_self.updateColumnsArray("remove", i_node.get("itemId"));
			a_removed.push(o_properties);
		}

		return a_removed;
	},

	removeColumn: function (s_column) {

		var i_self = this;
		var i_root = i_self.getRootNode();

		var i_node = i_root.findChild("itemId", s_column, true);

		if (i_node) {

			i_node.remove();

			i_self.updateColumnsArray("remove", s_column);
		}
	},

	removeAffiliation: function (s_name) {

		var i_self = this;
		var i_root = i_self.getRootNode();
		var a_toRemove = [];

		i_root.cascadeBy(function (i_record) {

			var o_values = i_record.get("properties") || {};

			if (o_values.nodeType == "affiliation-item") {

				if (o_values.name == s_name) {

					if (a_toRemove.indexOf(i_record.get("itemId")) < 0) {

						a_toRemove.push(i_record.get("itemId"));
					}
				}
			}
		});

		a_toRemove = Ext.Array.filter(a_toRemove, function (value) {
			return value;
		});

		Ext.Array.each(a_toRemove, function (s_node) {
			i_self.removeColumn(s_node);
		});
	},

	removeRelation: function (s_entity) {

		var i_self = this;
		var i_root = i_self.getRootNode();
		var a_toRemove = [];

		i_root.cascadeBy(function (i_record) {

			var o_values = i_record.get("properties") || {};

			if (o_values.entityClass == s_entity) {

				if (a_toRemove.indexOf(i_record.get("itemId")) < 0) {

					a_toRemove.push(i_record.get("itemId"));
				}
			}
		});

		a_toRemove = Ext.Array.filter(a_toRemove, function (value) {
			return value;
		});

		a_toRemove.reverse();

		Ext.Array.each(a_toRemove, function (s_node) {
			i_self.removeColumn(s_node);
		});
	},

	updateColumnsArray: function (action, s_column) {

		var i_self = this;
		var o_keys = i_self.getKeys();
		var n_index;

		switch (action) {
			case "add":
				n_index = o_keys.column.indexOf(s_column);
				if (n_index < 0) {
					o_keys.column.push(s_column);
				}
				break;
			case "remove":
				n_index = o_keys.column.indexOf(s_column);
				if (n_index > -1) {
					o_keys.column.splice(n_index, 1);
				}
				break;
		}
	},

	columnAlreadyExists: function (s_column) {

		var i_self = this;
		var o_keys = i_self.getKeys();
		return o_keys.column.indexOf(s_column) > -1;
	},

	addToLayout: function (a_records, i_layout) {

		var i_self = this;

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

			var o_properties = i_record.get("properties");

			var o_config;
			var s_id;

			if (o_properties.nodeType == "uiLayout") {
				o_config = i_self.createLayoutNode(o_properties.layoutType, o_properties.region, o_properties, [], [], [], []);
			}
			else if (o_properties.nodeType == "group") {

				s_id = "group-" + ip2.unique();

				o_config = {
					leaf: false,
					expanded: false,
					allowDrop: true,
					allowDrag: true,
					properties: {
						nodeType: "group",
						xtype: o_properties.xtype,
						name: s_id,
						title: {
							da: s_id,
							en: s_id
						},
						bodyPadding: 10,
						collapsible: true,
						collapsed: false,
						defaults: {
							anchor: "100%",
							labelWidth: 160
						}
					},
					children: []
				};
			}

			var i_child = i_layout.appendChild(o_config);
			i_child.commit();
		});
	},

	addHeaderItems: function() {

		var i_self = this;

		var a_items = [];

		var o_entity = i_self.getEntity();

		var a_columns = Ext.Array.from(o_entity.columns);

		var o_view = o_entity.ui.forms[i_self.getContext()] || {
			designerContext: ""
		};

		var o_pdColumn = Ext.Array.findBy(a_columns, function(o_column) {
			return o_column.pd;
		});

		if (o_pdColumn) {

			var i_store = Ext.create("Ext.data.Store", {
				autoLoad: true,
				fields: [
					{
						name: "name",
						type: "auto"
					},
					{
						name: "label",
						type: "auto"
					}
				],
				proxy: {
					url: o_pdColumn.pd,
					type: "ajax",
					actionMethods: {
						read: "POST"
					},
					paramsAsJson: true,
					extractResponseData: function(i_response) {

						var a_result = Ext.decode(i_response.responseText, true) || [];

						var a_filtered = Ext.Array.filter(a_result, function(o_config) {
							return o_config.type == "formCollection";
						});

						Portfolio.pd.util.Cache.set(o_pdColumn.pd, a_result);

						i_self.setFormCollections(a_filtered);
						i_self.setDefinitions(a_result);

						return {
							success: true,
							rows: a_filtered
						};
					},
					reader: {
						type: "json",
						rootProperty: "rows",
						
					}
				}
			});

			var i_formCollection = Ext.widget("combobox", {
				editable: false,
				store: i_store,
				flex: 1,
				valueField: "name",
				displayField: "label",
				ui: "function-field",
				displayTpl: Ext.create("Ext.XTemplate",
					"<tpl for=\".\">",
					"{[typeof values === \"string\" ? values : this.renderer(values.label)]}",
					"<tpl if=\"xindex < xcount\">,</tpl>",
					"</tpl>",
					{
						renderer: function(value) {
							return ip2.i18n(value, value);
						}
					}
				),
				tpl: Ext.create("Ext.XTemplate",
					"<tpl for=\".\">",
						"<li role=\"option\" class=\"x-boundlist-item\" style=\"text-overflow: ellipsis; white-space: nowrap; overflow:hidden;\">",
							"{[this.getValue(values.label)]}",
						"</li>",
					"</tpl>",
					{
						getValue: function(value) {
							return ip2.i18n(value, value);
						}
					}
				),
				listeners: {
					change: {
						fn: function(i_field, newValue, oldValue) {

							i_self.fireEvent("collectionchange", newValue, oldValue);
						}
					}
				}
			});

			i_store.on({
				load: {
					fn: function(i_store, a_records) {
						i_formCollection.setValue(o_view.designerContext || i_store.getAt(0));
						
					},
					single: true
				}
			});

			i_self.setCollectionPicker(i_formCollection);
	
			a_items.push(i_formCollection);

			i_self.enableBubble("collectionchange");
	
		}

		return a_items;
	},

	createFormLayout: function(o_config) {

		var i_self = this;

		var a_groups = i_self.createGroups(o_config);
		var a_relations = i_self.createRelations(o_config);
		var a_widgets = i_self.createWidgets(o_config);
		var a_affiliations = i_self.createAffiliations(o_config);

		var a_viewTabs = Ext.Array.from(o_config.tabs);

		var o_root = Ext.Array.findBy(a_viewTabs, function(o_tab) {
			return o_tab.contentRoot;
		}) || {
			properties: {
				nodeType: "content-root",
				name: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				title: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				layout: "anchor",
				bodyPadding: 20,
				autoScroll: true,
				defaults: {
					anchor: "100%",
					width: 800,
					labelWidth: 150
				}
			},
		};

		o_root = Ext.clone(o_root);

		delete o_root.itemId;
		delete o_root.index;
		delete o_root.contentRoot;

		var o_contentRoot = {
			itemId: "content-root",
			expanded: false,
			allowDrop: true,
			allowDrag: false,
			properties: Ext.apply({
				nodeType: "content-root",
				name: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				title: ip2.i18n({
					da: "Indhold",
					en: "Content"
				}),
				layout: "anchor",
				bodyPadding: 20,
				autoScroll: true,
				defaults: {
					anchor: "100%",
					width: 800,
					labelWidth: 150
				}
			}, o_root),
			children: []
		};

		var a_tabs = [];

		var a_temp = Ext.Array.from(o_config.tabs);

		a_temp = Ext.Array.filter(a_temp, function(o_tab) {
			return !o_tab.contentRoot;
		});

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

            var o_tab;

            if (o_config.type != "app-component") {
                
                o_tab = {
                    itemId: o_config.name,
                    expanded: true,
                    allowDrop: true,
                    allowDrag: true,
                    properties: Ext.apply({
                        nodeType: "tab-content"
                    }, o_config),
                    children: []
                };
    
                var a_tabGroups = Ext.Array.filter(a_groups, function(o_group) {
                    return o_group.properties.tabId == o_tab.itemId;
                });
    
                Ext.Array.each(a_tabGroups, function(o_group) {
                    Ext.Array.remove(a_groups, o_group);
                });
    
                if (o_config.uiLayout) {
    
                    Ext.apply(o_config, {
                        layout: "fit"
                    });
    
                    o_tab.children = o_tab.children.concat([
                        i_self.createLayoutNode(null, null, o_config.uiLayout, a_tabGroups, a_relations, a_widgets, a_affiliations)
                    ]);
                }
                else {
                    o_tab.children = a_tabGroups;
                }
            }
            else {

                var s_itemId = o_config.itemId;

                o_tab = {
                    itemId: s_itemId,
                    expanded: false,
                    allowDrop: true,
                    allowDrag: true,
                    leaf: true,
                    iconCls: "pf-monitor",
                    properties: Ext.applyIf(o_config, {
                        nodeType: "app-component",
                        name: s_itemId
                    })
                };
            }
            
			a_tabs.push(o_tab);
		});

		a_tabs.unshift(o_contentRoot);

		var o_tabs = {
			itemId: "tabs-root",
			expanded: true,
			allowDrop: true,
			allowDrag: false,
			properties: {
				nodeType: "tabs-root",
				name: ip2.i18n({
					da: "Tabs",
					en: "Tabs"
				}),
			},
			children: a_tabs
		};

		if (!o_config.uiLayout) {

			o_contentRoot.children = o_contentRoot.children.concat(a_groups);
			o_tabs.children = a_tabs.concat(a_relations).concat(a_affiliations).concat(a_widgets);
		}
		else {
			o_contentRoot.children = o_contentRoot.children.concat(
				[i_self.createLayoutNode(null, null, o_config.uiLayout, a_groups, a_relations, a_widgets, a_affiliations)
			]);
		}

		if (o_contentRoot.children.length > 0) {
			o_contentRoot.expanded = true;
		}

		return o_tabs;
	},

	markExtended: function(item) {

		var i_self = this;

		if (Ext.isObject(item)) {

			if (item.hasOwnProperty("name")) {

				Ext.apply(item, {
					extended: true
				});
			}

			Ext.Object.each(item, function(s_key, value) {
							
				if (Ext.isArray(value)) {
	
					i_self.markExtended(value);
				}

				if (Ext.isObject(value)) {

					i_self.markExtended(value);
				}
			});
		}
		else if (Ext.isArray(item)) {
	
			Ext.Array.each(item, function(temp) {

				if (Ext.isObject(temp)) {

					i_self.markExtended(temp);
				}
				else if (Ext.isArray(temp)) {

					i_self.markExtended(temp);
				}
			});
		}
	},

	updateFormCollection: function(a_values) {

		var i_self = this;

		i_self.fireEvent("collectionupdate", a_values);
	}
});
