Ext.define("Portfolio.designer.ui.domainModelEntityFormDesignerManager", {

	extend: "Ext.panel.Panel",

	alias: [
		"widget.ip2DomainModelEntityFormDesignerManager"
	],

	layout: {
		type: "hbox",
		align: "stretch"
	},

	config: {
		propertyPanel: null,
		previewPanel: null,
		editor: null,
		designer: null,
		util: null,
		selected: null,
		newRelations: 0,
		newColumns: 0,
		newAffiliations: 0,
		treeGrid: null,
		treeLayout: null,
		entity: null,
		entityManager: null,
		required: false,
		tabProperties: null,
		view: "portfolio",
		forms: []
	},

	requires: [
		"Portfolio.designer.ui.domainModelEntityFormDesignerPropertyGrid",
		"Portfolio.designer.ui.domainModelEntityFormDesignerTreeGrid",
		"Portfolio.entity.util.Handler",
		"Portfolio.designer.ui.form.layout.Tree",
		"Portfolio.designer.ui.form.layout.Component"
	],

	listeners: {
		newColumns: {
			fn: function (i_panel, n_columns) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();

				i_self.setNewColumns(n_columns);
				i_tree.fireEvent("newColumns");
			}
		},
		newAffiliations: {
			fn: function (i_panel, n_affiliations) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();

				i_self.setNewAffiliations(n_affiliations);
				i_tree.fireEvent("newAffiliations");
			}
		},
		newRelations: {
			fn: function (i_panel, n_relations) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();

				i_self.setNewRelations(n_relations);
				i_tree.fireEvent("newRelations");
			}
		},
		updateField: {
			fn: function (i_panel, i_record, b_updateSource) {

				var i_self = this;
				i_self.updateField(i_record, b_updateSource);
			}
		},
		updateGroup: {
			fn: function(i_panel, i_record) {

				var i_self = this;
				i_self.updateGroup(i_record);
			}
		},
		updateUiLayout: {
			fn: function (i_self, i_record) {
				i_self.updateUiLayout(i_record);
			}
		},
		entityChange: {
			fn: function (i_panel, o_values) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();

				i_tree.fireEvent("entityChange", i_tree, o_values);
			}
		},
		updateAffiliation: {
			fn: function (i_panel, o_values) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();

				i_tree.fireEvent("updateAffiliation", i_tree, o_values);
				i_treeLayout.fireEvent("updateAffiliation", i_treeLayout, o_values);
			}
		},
		updateRelation: {
			fn: function (i_panel, i_record) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();

				i_tree.fireEvent("updateRelation", i_tree, i_record);
				i_treeLayout.fireEvent("updateRelation", i_treeLayout, i_record);
			}
		},
		updateColumn: {
			fn: function (s_old, s_new) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();

				i_tree.fireEvent("updateColumn", s_old, s_new);
				i_treeLayout.fireEvent("updateColumn", s_old, s_new);
			}
		},
		removeColumn: {
			fn: function (s_colum) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();

				i_tree.fireEvent("removeColumn", s_colum);
				i_treeLayout.fireEvent("removeColumn", s_colum);
			}
		},
		removeRelation: {
			fn: function (i_panel, s_entity) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();

				i_tree.fireEvent("removeRelation", i_tree, s_entity);
				i_treeLayout.fireEvent("removeRelation", i_treeLayout, s_entity);
			}
		},
		removeAffiliation: {
			fn: function (s_name) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();

				i_tree.fireEvent("removeAffiliation", s_name);
				i_treeLayout.fireEvent("removeAffiliation", s_name);
			}
		},
		syncTrees: {
			fn: function(o_config) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();

				i_tree.fireEvent("syncTrees", o_config);
			}
		},
		collectionchange: {
			fn: function(newValue, oldValue) {

				var i_self = this;
				var i_tree = i_self.getTreeGrid();
				var i_treeLayout = i_self.getTreeLayout();
				var o_layoutKeys = i_treeLayout.getKeys();

				i_tree.fireEvent("syncup", i_tree, o_layoutKeys);
				i_tree.fireEvent("collectionchange", newValue, oldValue);
			}
		}
	},

	initComponent: function() {

		var i_self = this;

		var i_eastpanel = i_self.createEast();

		i_self.callParent();

		i_self.add([
			i_self.createLayoutTree(),
			i_eastpanel
		]);
	},


	createEast: function() {

		var i_self = this;

		var i_pnlPreview = Ext.widget("panel", {
			layout: "fit",
			flex: 1,
			split: true,
			title: ip2.i18n({
				da: "Preview",
				en: "Preview"
			}),
			hidden: true
		});

		i_self.setPreviewPanel(i_pnlPreview);

		var i_eastpanel = Ext.widget("panel", {
			flex: 1,
			layout: {
				type: "vbox",
				align: "stretch"
			},
			split: true,
			items: [
				i_pnlPreview,
				i_self.createPropertyArea()
			]
		});

		return i_eastpanel;
	},

	createPropertyArea: function() {

		var i_self = this;

		var i_pnlProperties = Ext.widget("ip2DomainModelEntityFormDesignerPropertyGrid", {
			layout: "fit",
			flex: 1,
			split: true,
			features: [{
				ftype: "grouping"
			}],
			title: ip2.i18n({
				da: "Egenskaber",
				en: "Properties"
			}),
			listeners: {
				propertychange: {
					fn: function (o_source) {

						var i_editor = i_self.getEditor();

						var o_clone = Ext.clone(o_source);

						i_editor.suspendEvent("change");
						i_editor.setValue(o_clone);
						i_editor.resumeEvent("change");

						i_self.doUpdate(o_clone);
					}
				}
			}
		});

		var i_store = i_pnlProperties.getStore();

		var i_grouper = Ext.create("Ext.util.Grouper", {
			property: "category",
			groupFn: function (i_record) {
				return i_record.get("category");
			}
		});

		i_store.setGrouper(i_grouper);

		var i_plugin = i_pnlProperties.getPlugin();

		i_plugin.on({
			beforeedit: {
				fn: function (i_plugin, i_context) {

					var i_record = i_context.record;
					var s_id = i_record.getId();

					var b_edit = true;

					var a_disallow = [
						"type"
					];

					if (b_edit) {

						b_edit = !Ext.Array.contains(a_disallow, s_id);
					}

					return b_edit;
				}
			}
		});

		var i_acetextfield = Ext.widget("acetextarea", {
			xtype: "acetextarea",
			hideLabel: true,
			name: "properties",
			itemId: "editor-properties",
			mode: "json",
			asJson: true
		});

		var i_pnlSource = Ext.widget("panel", {
			layout: "fit",
			flex: 2,
			split: true,
			title: ip2.i18n({
				da: "Kildetext",
				en: "Source text"
			}),
			items: [
				i_acetextfield
			],
			listeners: {
				activate: {
					fn: function (i_panel) {

						var i_field = i_panel.down("[name=properties]");
						var value = i_field.getValue();

						i_field.suspendEvent("change");
						i_field.setValue(value);
						i_field.resetOriginalValue();
						i_field.resumeEvent("change");
					}
				}
			}
		});

		i_acetextfield.on({
			change: {
				fn: function (i_field, o_values) {

					if (i_field.isValid() && o_values) {

						i_pnlProperties.setSource(o_values);

						i_self.doUpdate(o_values, true);
					}
				},
				buffer: 250
			}
		});


		var i_tabProperties = Ext.widget("tabpanel", {
			layout: "fit",
			flex: 1,
			hidden: true,
			split: true,
			items: [
				i_pnlProperties,
				i_pnlSource
			]
		});


		var i_util = Ext.create("Portfolio.entity.util.Handler", {});

		i_self.setPropertyPanel(i_pnlProperties);
		i_self.setEditor(i_acetextfield);
		i_self.setTabProperties(i_tabProperties);
		i_self.setUtil(i_util);

		i_tabProperties.setActiveTab(0);

		return i_tabProperties;
	},

	createTree: function() {

		var i_self = this;
		var i_propertyField = i_self.getEditor();
		var i_designer = i_self.getDesigner();
		var i_entityManager = i_self.getEntityManager();
		var o_entity = i_self.getEntity();
		var b_required = i_self.getRequired();
		var i_treeLayout = i_self.getTreeLayout();

		var o_layoutKeys = Ext.clone(i_treeLayout.getKeys());

		var i_tree = Ext.create("Portfolio.designer.ui.domainModelEntityFormDesignerTreeGrid", {
			title: ip2.i18n({
				da: "Felter",
				en: "Fields"
			}),
			flex: 1,
			border: false,
			designer: i_designer,
			formDesigner: i_self,
			entity: o_entity,
			entityManager: i_entityManager,
			propertiesField: i_propertyField,
			required: b_required,
			uiName: i_self.getView(),
			keys: o_layoutKeys
		});

		i_self.setTreeGrid(i_tree);

		return i_tree;
	},

	createLayoutTree: function() {

		var i_self = this;

		var i_treeLayout = Ext.widget("form.designer.layout.tree", {
			title: "Layout",
			entity: i_self.getEntity(),
			entityManager: i_self.getEntityManager(),
			designer: i_self.getDesigner(),
			context: i_self.getView(),
			flex: 2,
			collapsible: true,
			collapseDirection: "left", 
			split: true,
			listeners: {
				select: {
					fn: function (i_view, i_record) {

						var o_properties = i_record.get("properties");
						var i_pnlPreview = i_self.getPreviewPanel();
						var i_pnlProperties = i_self.getPropertyPanel();
						var i_tabProperties = i_self.getTabProperties();
						var i_editor = i_self.getEditor();
						var i_treeLayout = i_self.getTreeLayout();
						var i_collectionPicker = i_treeLayout.getCollectionPicker();

						i_pnlPreview.setLoading(true);

						Ext.suspendLayouts();

						var o_entity = i_treeLayout.getEntity();
						var s_context = i_treeLayout.getContext();

						var o_data = {};

						var i_entityManager = i_self.getEntityManager();
						var i_relationManager = i_entityManager.getRelationManager();
						var i_designer = i_self.getDesigner();

						i_pnlPreview.removeAll(true);

						var i_header = i_pnlPreview.getHeader();
						var a_items = [];
						var o_clone = Ext.apply({}, Ext.clone(o_properties));
						var i_panel;
						var a_relations = [];
						var i_form;
						var i_actionBar;

						var s_modelId = i_entityManager.modelId || "";

						var s_dmd = i_entityManager.modelId ?
							s_modelId.indexOf("/") ? s_modelId : "dmd/" + s_modelId
							: "dmd/" + ip2.cleanPath(i_designer.dmdFile).split("/").pop();

						i_header.remove(i_header.getComponent("picker-type"), true);

						var o_oldData = null;

						var o_sourceConfig = Ext.apply({}, {
							title: {
								editor: {
									xtype: "i18n-textfield"
								},
								renderer: function (value) {
									return ip2.i18n(value);
								}
							},
							labelStyle: {
								editor: {
									xtype: "acetextarea",
									mode: "json",
									height: 100,
									asJson: true
								},
								renderer: function (value) {
									return Ext.encode(value);
								}
							},
							fieldLabel: {
								editor: {
									xtype: "i18n-textfield"
								},
								renderer: function (value) {
									return ip2.i18n(value);
								}
							},
							emptyText: {
								editor: {
									xtype: "i18n-textfield"
								},
								renderer: function (value) {
									return ip2.i18n(value);
								}
							},
							defaults: {
								editor: {
									xtype: "acetextarea",
									mode: "json",
									height: 100,
									asJson: true
								},
								renderer: function (value) {
									return Ext.encode(value);
								}
							}
						});


						var i_promise = new Ext.Promise(function(f_resolve, f_reject) {

							if (i_collectionPicker) {

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

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

								o_oldData = {};

								o_oldData[o_pdColumn.name] = Ext.encode({
									fcid: i_collectionPicker.getValue()
								});

								i_self.doSave(null, false,o_pdColumn.name, function(o_result) {

									var o_return = o_result[o_entity.name + "." + o_pdColumn.name + "." + i_collectionPicker.getValue()];

									f_resolve(o_return);
								});
							}
							else {
								var o_temp = i_self.doSave();
								f_resolve(o_temp);
							}

						});

						i_promise.then(function(o_result) {

							Ext.apply(o_result, {
								layouts: o_entity.ui.forms[i_treeLayout.getContext()].layouts || []
							});

							o_data = {
								ui: {
									forms: {
										portfolio: o_result,
									}
								}
							};

							a_relations = i_relationManager.doSave({
								name: o_entity.name
							});
	
							o_data.relations = a_relations;

							if (o_properties.nodeType == "form-root") {

								i_form = Ext.widget("portfolio-entity-form", {
									action: "create",
									dmd: s_dmd,
									entity: o_entity.name,
									view: s_context,
									context: "form",
									language: "da",
									dataConfig: o_data,
									readOnly: true,
									linkable: false,
									oldData: o_oldData,
									listeners: {
										contentReady: {
											fn: function(i_content, i_entityform) {

												i_actionBar = i_entityform.getActionbar();
												i_actionBar.disable();
		
												i_pnlPreview.show();
												i_tabProperties.hide();
												i_pnlPreview.add(i_entityform);
											}
										}
									}
								});
							}
							else if (o_properties.nodeType == "tabs-root") {

								i_form = Ext.widget("portfolio-entity-form", {
									action: "create",
									dmd: s_dmd,
									entity: o_entity.name,
									view: s_context,
									context: "form",
									language: "da",
									oldData: o_oldData,
									dataConfig: o_data
								});

								var i_tabarea = i_form.getTabPanel();

								i_pnlPreview.show();
								i_tabProperties.hide();
								i_pnlPreview.add(i_tabarea);

							}
							else if (o_properties.nodeType == "content-root") {

								i_self.setSelected(i_record);
	
								i_form = Ext.widget("portfolio-entity-form", {
									action: "create",
									dmd: s_dmd,
									entity: o_entity.name,
									view: s_context,
									context: "form",
									language: "da",
									dataConfig: o_data,
									oldData: o_oldData
								});
	
								var i_content = i_form.getContent();
	
								i_pnlPreview.show();
								i_pnlPreview.add(i_content);

								delete o_clone.nodeType;
								delete o_clone.name;
								delete o_clone.properties;
								delete o_clone.uiLayout;
								delete o_clone.extended;

								var i_layoutStore = Ext.create("Ext.data.Store", {
									fields: [
										{
											name: "key",
											type: "string"
										},
										{
											name: "value",
											type: "auto"
										}
									],
									autoLoad: true,
									data: [
										{
											key: "anchor",
											value: "anchor"
										},
										{
											key: "hbox",
											value: {
												type: "hbox",
												align: "stretch"
											}
										},
										{
											key: "vbox",
											value: {
												type: "vbox",
												align: "stretch"
											}
										},
										{
											key: "fit",
											value: "fit"
										}
									]
								});

								Ext.apply(o_sourceConfig, {
									layout: {
										editor: {
											xtype: "combobox",
											store: i_layoutStore,
											value: "anchor",
											displayField: "key",
											valueField: "value"
										},
										renderer: function (value) {

											var s_return = value;

											if (Ext.isObject(value)) {
												s_return = value.type;
											}
											return s_return;
										}
									}
								});

								i_pnlProperties.setSource(o_clone, o_sourceConfig);

								i_editor.suspendEvent("change");
								i_editor.setValue(o_clone);
								i_editor.resetOriginalValue();
								i_editor.resumeEvent("change");
								
								i_tabProperties.show();
							}
							else if (o_properties.nodeType == "tab-content") {

								i_self.setSelected(i_record);
	
								i_form = Ext.widget("portfolio-entity-form", {
									action: "create",
									dmd: s_dmd,
									entity: o_entity.name,
									view: s_context,
									context: "form",
									language: "da",
									dataConfig: o_data,
									oldData: o_oldData
								});

								var i_tabpanel = i_form.getTabPanel();
	
								var i_tab = i_tabpanel.getComponent(o_properties.name);
	
								i_pnlPreview.show();
								i_pnlPreview.add(i_tab);

								var i_layoutStore = Ext.create("Ext.data.Store", {
									fields: [
										{
											name: "key",
											type: "string"
										},
										{
											name: "value",
											type: "auto"
										}
									],
									autoLoad: true,
									data: [
										{
											key: "anchor",
											value: "anchor"
										},
										{
											key: "hbox",
											value: {
												type: "hbox",
												align: "stretch"
											}
										},
										{
											key: "vbox",
											value: {
												type: "vbox",
												align: "stretch"
											}
										},
										{
											key: "fit",
											value: "fit"
										}
									]
								});

								Ext.apply(o_sourceConfig, {
									layout: {
										editor: {
											xtype: "combobox",
											store: i_layoutStore,
											value: "anchor",
											displayField: "key",
											valueField: "value"
										},
										renderer: function (value) {

											var s_return = value;

											if (Ext.isObject(value)) {
												s_return = value.type;
											}
											return s_return;
										}
									}
								});

								delete o_clone.itemId;
								delete o_clone.nodeType;
								delete o_clone.group;
								delete o_clone.index;
								delete o_clone.entityClass;
								delete o_clone.contentRoot;
								delete o_clone.name;
								delete o_clone.uiLayout;
								delete o_clone.extended;

								o_clone.layout = o_clone.layout || "anchor";

								i_pnlProperties.setSource(o_clone, o_sourceConfig);

								i_editor.suspendEvent("change");
								i_editor.setValue(o_clone);
								i_editor.resetOriginalValue();
								i_editor.resumeEvent("change");
								
								i_tabProperties.show();
							}
							else if (o_properties.nodeType == "app-component") {

								delete o_clone.itemId;
								delete o_clone.nodeType;
								delete o_clone.group;
								delete o_clone.index;
								delete o_clone.entityClass;
								delete o_clone.contentRoot;
								delete o_clone.name;
								delete o_clone.uiLayout;
								delete o_clone.extended;

								i_self.setSelected(i_record);

								var o_config = o_properties.config || {};
								var s_class = o_properties.main || "";
								var o_paths = o_properties.path || {};

								if (s_class) {

									if (!Ext.Object.isEmpty(o_paths)) {
										Ext.Loader.setConfig(o_paths);
									}
	
									try {
										var i_component = Ext.create(s_class, o_config);

										i_pnlPreview.add([
											i_component
										]);
									} 
									catch(o_err) {
										i_pnlPreview.setHtml(o_err.message);
									}

									i_pnlPreview.show();

									Ext.apply(o_sourceConfig, {
										path: {
											editor: {
												xtype: "acetextarea",
												mode: "javascript",
												asJson: true
											},
											renderer: function (value) {
	
												return Ext.encode(value, true) || value;
											}
										},
										config: {
											editor: {
												xtype: "acetextarea",
												mode: "javascript",
												asJson: true
											},
											renderer: function (value) {
	
												return Ext.encode(value, true) || value;
											}
										}
									});
								} 

								i_pnlProperties.setSource(o_clone, o_sourceConfig);

								i_editor.suspendEvent("change");
								i_editor.setValue(o_clone);
								i_editor.resetOriginalValue();
								i_editor.resumeEvent("change");
								
								i_tabProperties.show();
							}
							else if(o_properties.nodeType == "groups") {

								var a_children = i_record.childNodes;

								Ext.Array.each(a_children, function (i_record) {
									var i_fieldset = i_self.createPreviewGroup(i_record);
									a_items.push(i_fieldset);
								});

								i_panel = Ext.widget("panel", {
									layout: "anchor",
									border: false,
									bodyPadding: 10,
									defaults: {
										anchor: "100%",
										maxWidth: 800,
										labelWidth: 150
									},
									autoScroll: true,
									items: a_items
								});

								i_pnlPreview.add(i_panel);
								i_pnlPreview.show();
								i_tabProperties.hide();
							}
							else {

								var i_parentNode = i_record.parentNode || i_record;

								var o_parentProperties = i_parentNode.get("properties") || {
									nodeType: "root"
								};
								
								var i_picker;

								if (o_properties.nodeType == "field" &&
									!o_properties.isHost &&
									!o_parentProperties.isHost) {

									i_self.setSelected(i_record);

									a_items = i_self.createFieldPreview(o_clone);

									i_picker = a_items.shift();

									i_pnlPreview.add(a_items);
									i_header.add(i_picker);

									i_pnlPreview.show();
									i_tabProperties.show();
								}
								else if (o_properties.nodeType == "pd-field" && !o_properties.extended) {

									i_self.setSelected(i_record);

									if (o_clone.apperence) {

										Ext.apply(o_clone, {
											type: o_clone.apperence
										});

										delete o_clone.apperence;
									}
									
									a_items = i_self.createFieldPreview(o_clone);

									i_picker = a_items.shift();

									i_pnlPreview.add(a_items);
									i_header.add(i_picker);

									i_pnlPreview.show();
									i_tabProperties.show();
								}
								else if(o_properties.nodeType == "group") {

									i_self.setSelected(i_record);
									
									var i_fieldset = i_self.createPreviewGroup(i_record);

									i_panel = Ext.widget("panel", {
										layout: "anchor",
										bodyPadding: 10,
										defaults: {
											anchor: "100%",
											maxWidth: 800,
											labelWidth: 300
										},
										autoScroll: true,
										items: [i_fieldset]
									});

									i_pnlPreview.add(i_panel);
									i_pnlPreview.show();
									i_tabProperties.show();

									var i_xtypeStore = Ext.create("Ext.data.Store", {
										fields: ["key", "value"],
										autoLoad: true,
										data: [
											{
												key: "fieldset",
												value: "fieldset"
											},
											{
												key: "fieldcontainer",
												value: "fieldcontainer"
											}
										]
									});

									var i_layoutStore = Ext.create("Ext.data.Store", {
										fields: [
											{
												name: "key",
												type: "string"
											},
											{
												name: "value",
												type: "auto"
											}
										],
										autoLoad: true,
										data: [
											{
												key: "anchor",
												value: "anchor"
											},
											{
												key: "hbox",
												value: {
													type: "hbox",
													align: "stretch"
												}
											},
											{
												key: "vbox",
												value: {
													type: "vbox",
													align: "stretch"
												}
											},
											{
												key: "fit",
												value: "fit"
											}
										]
									});

									Ext.apply(o_sourceConfig, {
										xtype: {
											editor: {
												xtype: "combobox",
												store: i_xtypeStore,
												value: "fieldset",
												displayField: "key",
												valueField: "value"
											}
										},
										layout: {
											editor: {
												xtype: "combobox",
												store: i_layoutStore,
												value: "fieldset",
												displayField: "key",
												valueField: "value"
											},
											renderer: function (value) {

												var s_return = value;

												if (Ext.isObject(value)) {
													s_return = value.type;
												}
												return s_return;
											}
										}
									});

									delete o_clone.nodeType;
									delete o_clone.group;
									delete o_clone.entityClass;
									delete o_clone.tabId;

									o_clone.xtype = o_clone.xtype || "fieldset";
									o_clone.layout = o_clone.layout || "anchor";

									i_pnlProperties.setSource(o_clone, o_sourceConfig);

									i_editor.suspendEvent("change");
									i_editor.setValue(o_clone);
									i_editor.resetOriginalValue();
									i_editor.resumeEvent("change");

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

									i_self.setSelected(i_record);

									delete o_clone.nodeType;
									delete o_clone.entityClass;
									delete o_clone.type;
									delete o_clone.path;

									Ext.apply(o_sourceConfig, {
										window: {
											editor: {
												xtype: "acetextarea",
												mode: "json",
												height: 100,
												asJson: true
											},
											renderer: function (value) {
												return Ext.encode(value);
											}
										}
									});

									i_pnlProperties.setSource(o_clone, o_sourceConfig);

									i_editor.suspendEvent("change");
									i_editor.setValue(o_clone);
									i_editor.resetOriginalValue();
									i_editor.resumeEvent("change");

									i_pnlPreview.hide();
									i_tabProperties.show();

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

									i_self.setSelected(i_record);

									delete o_clone.nodeType;
									delete o_clone.entityClass;
									delete o_clone.name;
									delete o_clone.layoutType;
									delete o_clone.layout;
									delete o_clone.type;

									var i_regionStore = Ext.create("Ext.data.Store", {
										fields: ["key", "value"],
										autoLoad: true,
										data: [
											{
												key: "center",
												value: "center"
											},
											{
												key: "west",
												value: "west"
											},
											{
												key: "east",
												value: "east"
											},
											{
												key: "north",
												value: "north"
											},
											{
												key: "south",
												value: "south"
											}
										]
									});


									Ext.apply(o_sourceConfig, {
										region: {
											editor: {
												xtype: "combobox",
												store: i_regionStore,
												value: "fieldset",
												displayField: "key",
												valueField: "value"
											}
										}
									});

									i_pnlProperties.setSource(o_clone, o_sourceConfig);

									//var a_layouts = i_self.createLayoutPreview(i_record, o_properties, o_data, o_oldData);

									i_editor.suspendEvent("change");
									i_editor.setValue(o_clone);
									i_editor.resetOriginalValue();
									i_editor.resumeEvent("change");

									//i_pnlPreview.add(a_layouts);

									i_pnlPreview.hide();
									i_tabProperties.show();

								}
								else {
									i_pnlPreview.hide();
									i_tabProperties.hide();
								}

								i_editor.fireEvent("change", i_editor, i_editor.getValue());
							}

							Ext.resumeLayouts(true);

							i_pnlPreview.setLoading(false);
						});
					},
					buffer: 250
				}
			}
		});

		i_self.setTreeLayout(i_treeLayout);

		var i_tree = i_self.createTree();

		var i_treeComponents = i_self.createComponentTree();

		var i_container = Ext.widget("container", {
			layout: {
				type: "hbox",
				align: "stretch"
			},
			flex: 1,
			items: [
				i_treeLayout,
				{
					xtype: "panel",
					flex: 1,
					layout: "accordion",
					collapsible: true,
					collapseDirection: "right",
					split: true,
					defaults: {
						xtype: "panel",
						collapsible: true,
						collapsed: true,
						border: false,
						autoScroll: true,
						layout: "fit",
						flex: 1
					},
					items: [
						i_treeComponents,
						i_tree
					]
				}
			]
		});

		return i_container;
	},

	createComponentTree: function(o_view) {

		var i_self = this;

		var i_treeComponents = Ext.widget("form.designer.layout.component", {
			title: ip2.i18n({
				da: "Komponenter",
				en: "Components"
			}),
			flex: 1,
			border: false,
			entity: i_self.getEntity(),
			entityManager: i_self.getEntityManager(),
			designer: i_self.getDesigner()
		});


		return i_treeComponents;
	},

	createPreviewGroup: function(i_record) {

		var i_self = this;

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

		o_properties.defaults = o_properties.defaults || {
			anchor: "100%",
			labelWidth: 160
		};

		delete o_properties.entityClass;
		delete o_properties.nodeType;

		var s_type = o_properties.xtype || "fieldset";

		var i_fieldgroup = Ext.widget(s_type, Ext.applyIf({
			title: ip2.i18n(o_properties.title)
		}, o_properties));

		var a_children = i_record.childNodes;

		var a_items = [];

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

			var a_fields = i_self.createField(i_record.get("properties"));
			a_items = a_items.concat(a_fields);
		});

		i_fieldgroup.add(a_items);
		return i_fieldgroup;
	},

	createFieldPreview: function(o_properties) {

		var i_self = this;
		var i_editor = i_self.getEditor();
		var i_properties = i_self.getPropertyPanel();

		var o_uirules = ip2.uirules;

		var i_panel = Ext.widget("panel", {
			layout: "anchor",
			bodyPadding: 10,
			autoScroll: true,
			defaults: {
				anchor: "100%",
				labelWidth: 160
			}
		});

		var a_data = [];
		var a_sort = [];
		var a_items = [];

		Ext.Object.each(o_uirules.collections, function(s_key) {
			var o_field = o_uirules.collections[s_key];
			if (!o_field.apply) {
				a_sort.push(s_key);
			}
			if (o_field.apply && !o_field.apply.type) {
				a_sort.push(s_key);
			}
		});

		a_sort.sort();

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

			var o_value = {
				key: s_key,
				value: s_key
			};
			a_data.push(o_value);
		});

		var i_store = Ext.create("Ext.data.Store", {
			fields: [
				{
					name: "key", type: "auto"
				},
				{
					name: "value", type: "auto"
				}
			],
			data: a_data
		});

		var i_picker = Ext.widget("combobox", {
			store: i_store,
			valueField: "value",
			displayField: "key",
			forceSelection: true,
			typeAHead: true,
			width: 300,
			queryMode: "local",
			queryCaching: false,
			triggerAction: "all",
			fieldLabel: ip2.i18n({
				da: "Type",
				en: "Type"
			}),
			sorters:[{
				property: "key",
				direction: "ASC"
			}],
			name: "type",
			itemId: "picker-type",
			ui: "function-field"
		});

		var a_fields = i_self.createField(o_properties);
		var i_field = a_fields[0];
		var s_type = o_properties.type;
		var o_config = Ext.clone(o_properties);

		if (i_field && i_field.xtype !== "container") {
			i_field.itemId = "customfield";
			s_type = i_field.type;
			o_config = Ext.clone(i_field.initialConfig);
		}
		else {
			s_type = o_properties.type;
		}

		i_panel.add(a_fields);

		i_picker.on({
			select: {
				fn: function(i_field, i_record) {

					var i_editor = i_self.getEditor();
					var i_customfield = i_self.getPreviewPanel().down("#customfield");
					var o_config = i_customfield._xpdConfig || {};

					if (Ext.isEmpty(o_config)) {
						o_config = i_editor.getValue();
					}

					o_config.type = i_record.get("value");

					var o_values = Ext.clone(o_config);

					try {

						var a_fields = i_self.createField(o_config);
						var i_new = a_fields[0];

						if (i_new) {
							i_new.itemId = "customfield";
							o_values = i_self.getProperties(i_new.initialConfig, o_config, o_config.type);
						}

						var i_pnlPreview = i_self.getPreviewPanel();
						i_pnlPreview.removeAll(true);

						var i_panel = Ext.widget("panel", {
							layout: "anchor",
							bodyPadding: 10,
							autoScroll: true,
							defaults: {
								anchor: "100%",
								labelWidth: 160
							}
						});

						i_panel.add(a_fields);

						i_pnlPreview.add(i_panel);

						i_editor.suspendEvent("change");
						i_editor.setValue(o_values);
						i_editor.resetOriginalValue();
						i_editor.resumeEvent("change");

						var o_sourceConfig = i_self.getSourceObject(o_values, o_config.type);

						i_properties.setSource(o_sourceConfig.data, o_sourceConfig.config);

						i_self.doUpdate(o_values);

					}
					catch (err) {}
				}
			}
		});

		i_picker.setValue(s_type);

		if (i_self.required) {
			i_picker.setDisabled(true);
		}

		var o_values = i_self.getProperties(o_config, o_properties, s_type);

		o_values.fieldLabel = o_values.fieldLabel || "";

		a_items.push(i_picker);
		a_items.push(i_panel);

		i_editor.suspendEvent("change");
		i_editor.setValue(o_values);
		i_editor.resetOriginalValue();
		i_editor.resumeEvent("change");

		var o_sourceConfig = i_self.getSourceObject(o_values, s_type);

		i_properties.setSource(o_sourceConfig.data, o_sourceConfig.config);

		return a_items;
	},

	createLayoutPreview: function(i_record, o_properties, o_data, o_oldData) {

		var i_self = this;
		var o_entity = i_self.getEntity();
		var i_designer = i_self.getDesigner();
		var i_entityManager = i_self.getEntityManager();
		var i_relationManager = i_entityManager.getRelationManager();
		var i_treeLayout = i_self.getTreeLayout();
		var i_collectionPicker = i_treeLayout.getCollectionPicker();

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

		var s_dmd = i_entityManager.modelId ?
			i_entityManager.modelId.indexOf("/") ? i_entityManager.modelId : "dmd/" + i_entityManager.modelId
			: "dmd/" + ip2.cleanPath(i_designer.dmdFile).split("/").pop();

		o_data = o_data || (function(){

			var o_context = i_self.doSave();

			Ext.apply(o_context, {
				layouts: o_entity.ui.forms[i_treeLayout.getContext()].layouts || []
			});

			return {
				ui: {
					forms: {
						portfolio: o_context
					}
				}
			};

		})();

		if (i_collectionPicker) {

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

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

			o_oldData = {};

			o_oldData[o_pdColumn.name] = Ext.encode({
				fcid: i_collectionPicker.getValue()
			});
		}

		var a_relations = i_relationManager.doSave({
			name: o_entity.name
		});

		o_data.relations = a_relations;

		var i_form = Ext.widget("portfolio-entity-form", {
			action: "create",
			dmd: s_dmd,
			entity: o_entity.name,
			view: "portfolio",
			context: "form",
			language: "da",
			dataConfig: o_data,
			oldData: o_oldData
		});

		var i_found = i_form.down("#" + o_properties.itemId);

		var i_contentArea = i_form.getContent();
		var a_found = [];

		if (i_found) {
			a_found.push(i_found);
		} 

		if (i_contentArea) {
			a_found = i_contentArea.queryBy(function (i_item) {
				if (i_item.isXType("panel", true) || i_item.isXType("tabpanel", true)) {
					var i_layout = i_item.getLayout();
	
					var b_result = i_layout.type == o_properties.type || i_item.xtype == o_properties.type;
					var i_ownerCt = i_item.ownerCt;
					var i_ownerLayout = i_ownerCt.getLayout();
	
					if (b_result && i_ownerCt.xtype != "form") {
						b_result = i_ownerLayout.type == o_parentProperties.type;
					}
	
					if (b_result && i_item.isXType("tabpanel", true)) {
						b_result = i_ownerLayout.type == o_parentProperties.type;
					}
	
					return b_result;
				}
				return false;
			});
		}

		var a_result = a_found;

		if (a_found.length > 1) {

			var a_filtered = i_parentNode.childNodes.filter(function(i_child) {

				var o_childProperties = i_child.get("properties");

				return o_properties.type == o_childProperties.type;
			});

			var n_index = a_filtered.indexOf(i_record);

			a_result = [a_found[n_index]];

		}

		var i_result = Ext.widget("container", {
			layout: "fit",
			flex: 1,
			items: a_result
		});

		return i_result;

	},

	getSourceObject: function(o_properties, s_collection) {

		var o_uirules = ip2.uirules;
		var o_collection = o_uirules.collections[s_collection];

		var o_rules = Ext.applyIf(Ext.clone(o_collection.properties), Ext.clone(o_uirules.properties));

		var o_config = {};
		var a_data = [];

		Ext.Object.each(o_rules, function(s_key, o_rule) {

			var value = o_rule.value || o_properties[s_key];

			var s_category = o_rule.category || ip2.i18n({
				da: "felt",
				en: "field"
			});

			if (o_rule) {
				switch (o_rule.type) {
					case "varchar":
					case "string":
						var o_field = Ext.apply({}, {
							editor: {
								xtype: "textfield"
							}
						});

						if (s_key == "name" ||
							s_key == "fieldLabel" ||
							s_key == "emptyText") {

							o_field = Ext.apply(o_field, {
								editor: {
									xtype: "i18n-textfield"
								},
								renderer: function(value) {
									return ip2.i18n(value);
								}
							});
						}
						o_config[s_key] = o_field;
						break;
					case "object":

						o_config[s_key] = Ext.apply({}, {
							editor: {
								xtype: "acetextarea",
								mode: "json",
								height: 100,
								asJson: true
							},
							renderer: function(value) {
								if (value) {
									return Ext.encode(value);
								}
								return null;
							}
						});
						break;
				}
			}

			var o_data = {
				name: s_key,
				value: value,
				category: s_category
			};

			a_data.push(o_data);
		});

		Ext.apply(o_config, {
			title: {
				editor: {
					xtype: "i18n-textfield"
				},
				renderer: function(value) {
					return ip2.i18n(value);
				}
			}
		});

		return {
			data: a_data,
			config: o_config
		};
	},

	getProperties: function(o_initalConfig, o_config, s_collection) {

		var o_value = Ext.Object.merge({}, o_initalConfig, o_config);

		var o_uirules = ip2.uirules;

		var o_collection = o_uirules.collections[s_collection];
		var o_properties = Ext.applyIf(Ext.clone(o_collection.properties), Ext.clone(o_uirules.properties));

		Ext.Object.each(o_value, function(s_key) {
			if (!o_properties.hasOwnProperty(s_key)) {
				delete o_value[s_key];
			}
		});

		Ext.Object.each(o_value, function(s_key, value) {
			if (Ext.isEmpty(value, false)) {
				delete o_value[s_key];
			}
		});

		Ext.Object.each(o_properties, function(s_key, o_config) {
			if (!o_value.hasOwnProperty(s_key)) {
				o_value[s_key] = o_config.value;
			}
		});

		Ext.Object.each(o_value, function(s_key, value) {
			if (/Args|Fn|__cid__|Event|shared/.test(s_key)) {
				delete o_value[s_key];
			}
		});

		delete o_value._xpdConfig;
		delete o_value.postprocess;
		delete o_value.uitype;
		delete o_value.uiclass;
		delete o_value.xtype;
		delete o_value.preprocess;
		delete o_value.itemId;
		delete o_value.nodeType;
		delete o_value.group;
		delete o_value.entityClass;
		delete o_value.title;
		delete o_value.name;
		delete o_value.sequence;

		return o_value;
	},

	createField: function(o_config) {

		var i_self = this;
		var o_entity = i_self.getEntity();
		var o_uirules = ip2.uirules;
		var o_uiTypeRules = ip2.loadUiTypeRules();
		var i_util = i_self.getUtil();
		var i_entityManager = i_self.getEntityManager();
		var i_columnManager = i_entityManager.getColumnManager();
		var i_designer = i_self.getDesigner();
		var i_store = i_columnManager.columnGrid.getStore();
		var i_column = i_store.findRecord("name", o_config.name) || {};

		var o_column = i_column.data || {};

		var o_uiTypes = ip2.getUiTypes();
		var s_dmd = i_entityManager.modelId ? "dmd/" + i_entityManager.modelId :
					"dmd/" + ip2.cleanPath(i_designer.dmdFile).split("/").pop();

		var o_field = Ext.apply({}, Ext.clone(o_config), Ext.clone(o_column));

		var a_values = [];

		if (o_field.uiType) {
			o_field.uitype = o_field.uiType;
			delete o_field.uiType;
		}
		if (o_field.uitype) {
			var o_uiType = o_uiTypes[o_field.uitype] || {};
			if (o_uiType.form && o_uiType.form.type) {
				var o_type = o_uiTypes[o_field.type];
				if (o_type) {
					o_field.type = o_uiType.form.type;
				}
			}
			delete o_field.uitype;
		}

		if (!o_field.type) {
			o_field.type = "varchar";
		}

		o_field.fieldLabel = o_field.fieldLabel || "";

		var o_collection;
		var b_found = false;
		var s_type = o_field.type;

		while (!b_found) {

			var o_current = o_uirules.collections[s_type] || {
				apply: {
					type: "varchar"
				}
			};

			if (o_current.apply && o_current.apply.type) {
				s_type = o_current.apply.type;
			}
			else if (o_current.apply && !o_current.apply.type) {
				b_found = true;
			}
			else {
				b_found = true;
			}
			if (b_found) {
				o_collection = o_current;
			}
		}

		o_field.type = s_type;

		Ext.Object.each(o_field, function(s_key, value) {
			if (Ext.isEmpty(value, false)) {
				delete o_field[s_key];
			}
		});

		if (o_collection.properties.hasOwnProperty("entity") && o_collection.properties.hasOwnProperty("dmd")) {
			if (!o_field.entity) {
				o_field.entity = o_entity.name;
			}
			if (!o_field.dmd) {
				o_field.dmd = s_dmd;
			}
		}

		var o_components = i_util.createUiComponent({
			rulesXpd: o_uirules.flatten,
			rulesJs: o_uiTypeRules,
			context: "form",
			config: o_field
		});

		Ext.Object.each(o_components, function(s_key) {

			var o_component = o_components[s_key];

			if (o_component.hasOwnProperty("dmd")) {
				if (!o_component.dmd) {
					o_component = Ext.apply(Ext.clone(o_component), {
						dmd: s_dmd
					});
				}
			}

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

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

			if (o_component.hasOwnProperty("entity")) {
				if (!o_component.entity) {
					o_component = Ext.apply(Ext.clone(o_component), {
						entity: i_self.getEntity().name
					});
				}
			}

			try {
				var i_field = Ext.create(o_component.uiclass, o_component);
				a_values.push(i_field);
			}
			catch (o_err) {

				var i_container = Ext.widget("container", {
					html: "<strong>Error:</strong></br>" + o_err.message + "</br><br><strong>StackTrace:</strong></br>" + o_err.stack,
					layout: "anchor",
					autoScroll: true
				});
				a_values.push(i_container);
			}
		});

		return a_values;
	},

	doSave: function (o_entity, b_save, s_column, f_callback) {

		var i_self = this;

		f_callback = f_callback || Ext.emptyFn;

		o_entity = o_entity || i_self.getEntity();

		var i_treeLayout = i_self.getTreeLayout();
		var i_treeGrid = i_self.getTreeGrid();

		var i_root = i_treeGrid.getRootNode();
		var i_entityRoot = i_root.findChild("itemId", "entity-" + o_entity.name, true);

		var o_form = i_treeLayout.doSave(o_entity);

		var a_definitions = i_treeLayout.getDefinitions() || [];

		if (b_save) {

			var s_context = i_treeLayout.getContext();
			var o_context = i_treeLayout.getEntity();
			
			var i_collectionPicker = i_treeLayout.getCollectionPicker();

			if (i_collectionPicker) {

				var s_fId = i_collectionPicker.getValue();

				o_form.designerContext = o_form.fcid = s_fId;

				var o_view = o_context.ui.forms[s_context];
				var a_layouts = Ext.Array.from(o_view.layouts);

				var n_current = - 1;

				var o_layout = Ext.Array.findBy(a_layouts, function(o_config, n_index) {
					n_current = n_index;
					return o_config.fcid == s_fId;
				});

				if (o_layout) {
					a_layouts[n_current] = Ext.clone(o_form);
				}
				else {
					a_layouts.push(Ext.clone(o_form));
				}

				delete o_form.fcid;

				Ext.Array.each(a_layouts, function(o_layout) {
					delete o_layout.designerContext;
				});

				Ext.apply(o_form, {
					layouts: Ext.clone(a_layouts)
				});
			}
		}
		
		Ext.Array.each(i_entityRoot.childNodes, function (i_record) {

			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: o_form.columns.length,
					group: ""
				});

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

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

		if (Ext.isFunction(f_callback) && Ext.emptyFn != f_callback) {

			var i_worker = new Worker("/portfolio/app/util/Worker.js");

			var f_message = function(i_event) {

				var i_worker = this;
				
				var o_result = Ext.decode(i_event.data, true) || i_event.data;

				i_worker.removeEventListener("message", f_message);
				
				i_worker.terminate();

				f_callback.call(i_self, o_result);
			};

			i_worker.addEventListener("message", f_message);

			Ext.apply(o_form, {
				layouts: o_entity.ui.forms[i_treeLayout.getContext()].layouts || []
			});

			i_worker.postMessage({
				definitions: a_definitions,
				view: o_form,
				entity: o_entity.name,
				property: s_column
			});
		}
		else {
			return o_form;
		}
	},

	getLayoutNode: function(i_node) {

		var i_self = this;

		var a_children = i_node.childNodes;
		var value;

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

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

			if (i_child.childNodes) {
				var o_result = i_self.getLayoutNode(i_child);
				var a_values = Ext.Array.from(o_result);
				a_items = a_items.concat(a_values);
			}
		});

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

		return value;
	},

	getRelationNode: function(i_node) {

		var i_self = this;

		var a_children = i_node.childNodes;

		var a_relations = [];

		Ext.Array.each(a_children, function(i_child, n_index) {
			var o_properties = i_child.get("properties");

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

			a_relations.push(o_values);
		});

		return a_relations;
	},

	getAffilationNode: function(i_node) {

		var a_children = i_node.childNodes;

		var a_affiliation = [];

		Ext.Array.each(a_children, function(i_child, n_index) {
			var o_properties = i_child.get("properties");

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

			a_affiliation.push(o_values);
		});

		return a_affiliation;
	},

	getWidgetNode: function(i_node) {

		var a_children = i_node.childNodes;

		var i_widget = {};

		Ext.Array.each(a_children, function(i_child) {
			var o_properties = i_child.get("properties");

			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,
				sequence: o_properties.index || o_properties.sequence || 0
			});

			i_widget[o_properties.name] = o_values;
		});

		return i_widget;
	},

	hasColumn: function(column, from) {

		var i_self = this;
		var i_tree = i_self.getTreeGrid();

		if (i_tree.keys.from.indexOf(from) > -1) {
			return true;
		}

		return false;
	},

	removeColumn: function(s_column) {

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

	doUpdate: function (o_values) {

		var i_self = this;
		var i_selected = i_self.getSelected();

		if (i_selected) {

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

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

				if (o_properties.nodeType == "field") {
					delete o_values.title;
					delete o_values.name;
					delete o_values.from;
				}

				o_values = Ext.applyIf(o_values, {
					nodeType: o_properties.nodeType,
					entityClass: o_properties.entityClass,
					relation: o_properties.relation
				});

				if (o_properties.nodeType == "field") {
					o_values = Ext.applyIf(o_values, {
						name: o_properties.name,
						title: o_properties.title,
						from: o_properties.from,
						isProperty: o_properties.isProperty,
						isHost: o_properties.isHost,
						hostField: o_properties.hostField
					});

					Ext.apply(o_values, {
						title: o_values.fieldLabel
					});

				}

				if (o_properties.nodeType == "pd-field") {
					o_values = Ext.applyIf(o_values, {
						name: o_properties.name,
						title: o_properties.title,
						from: o_properties.from,
						extended: o_properties.extended
					});

					Ext.apply(o_values, {
						title: o_values.fieldLabel
					});

				}

				if (o_properties.nodeType == "uiLayout") {
					o_values = Ext.applyIf(o_values, {
						type: o_properties.type,
						name: o_properties.name
					});
				}

				i_selected.set("properties", o_values);
				i_selected.commit();

				switch(o_properties.nodeType) {
					case "field":
					case "pd-field":
						i_self.fireEvent("updateField", i_self, i_selected, true);
						break;
					case "group":
						i_self.fireEvent("updateGroup", i_self, i_selected);
						break;
					case "uiLayout":
						i_self.fireEvent("updateUiLayout", i_self, i_selected);
						break;
				}
			}
			else if (o_properties.nodeType == "widget-item") {

				o_values = Ext.applyIf(o_values, {
					path: o_properties.path,
					nodeType: o_properties.nodeType
				});

				i_selected.set("properties", o_values);
				i_selected.commit();
			}
			else if (o_properties.nodeType == "relation-grid") {

				o_values = Ext.applyIf(o_values, {
					title: o_properties.title,
					nodeType: o_properties.nodeType,
					window: o_properties.window,
					entityClass: o_properties.entityClass
				});

				i_selected.set("properties", o_values);
				i_selected.commit();
			}
			else if (o_properties.nodeType == "content-root" || o_properties.nodeType == "tab-content") {

				o_values = Ext.applyIf(o_values, {
					name: o_properties.name,
					nodeType: o_properties.nodeType
				});

				i_selected.set("properties", o_values);
				i_selected.commit();
			}
			else if (o_properties.nodeType == "app-component") {

				Ext.apply(o_properties, o_values);
				
				i_selected.set("properties", o_properties);
				i_selected.commit();

				i_self.fireEvent("updateApp", i_self, i_selected);
			}
		}
	},

	updateGroup: function (i_record) {

		var i_self = this;

		var o_properties = i_record.get("properties");
		var i_pnlPreview = i_self.getPreviewPanel();

		var o_clone = Ext.apply({}, Ext.clone(o_properties));

		o_clone.defaults = o_clone.defaults || {
			anchor: "100%",
			labelWidth: 160
		};

		delete o_clone.entityClass;
		delete o_clone.nodeType;

		var s_type = o_clone.xtype || "fieldset";

		var i_fieldset = Ext.widget(s_type, Ext.applyIf({
			title: ip2.i18n(o_clone.title)
		}, o_clone));

		var a_children = i_record.childNodes;

		var a_items = [];

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

			var a_values = i_self.createField(i_record.get("properties"));
			a_items = a_items.concat(a_values);
		});

		i_fieldset.add(a_items);

		i_pnlPreview.removeAll(true);

		var i_panel = Ext.widget("panel", {
			layout: "anchor",
			bodyPadding: 10,
			defaults: {
				anchor: "100%"
			},
			autoScroll: true,
			items: [i_fieldset]
		});

		i_pnlPreview.add(i_panel);
	},

	updateUiLayout: function (i_record) {

		var i_self = this;

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

		var a_layouts = i_self.createLayoutPreview(i_record, o_properties);

		var i_pnlPreview = i_self.getPreviewPanel();

		Ext.suspendLayouts();

		i_pnlPreview.removeAll(true);

		i_pnlPreview.add(a_layouts);

		Ext.resumeLayouts(true);
	},

	updateField: function (i_record, b_updateSource) {

		var i_self = this;

		var o_properties = i_record.get("properties");
		var i_pnlPreview = i_self.getPreviewPanel();

		var o_clone = Ext.apply({}, Ext.clone(o_properties));
		try {

			Ext.Object.each(o_clone, function (s_key, value) {
				if (Ext.isArray(value)) {
					value = Ext.Array.filter(value, function (value) {
						return value !== "";
					});
					o_clone[s_key] = value;
				}
			});

			var a_fields = i_self.createField(o_clone);
			var i_field = a_fields[0];
			i_pnlPreview.removeAll(true);

			i_field.itemId = "customfield";

			var i_panel = Ext.widget("panel", {
				layout: "anchor",
				bodyPadding: 10,
				autoScroll: true,
				defaults: {
					anchor: "100%",
					labelWidth: 160
				}
			});

			i_panel.add(a_fields);

			i_pnlPreview.add(i_panel);

			i_pnlPreview.show();

			if (b_updateSource) {

				var i_properties = i_self.getPropertyPanel();

				var o_values = i_self.getProperties(i_field.initialConfig, o_properties, i_field.type);

				if (o_properties.hasOwnProperty("title")) {
					if (!o_properties.hasOwnProperty("fieldLabel")) {
						o_values.fieldLabel = o_properties.title;
					}
					else {
						o_values.title = o_values.fieldLabel;
					}
				}

				var o_sourceConfig = i_self.getSourceObject(o_values, i_field.type);
				i_properties.setSource(o_sourceConfig.data, o_sourceConfig.config);
			}
		}
		catch (err) { }
	},

	updateApp: function(i_selected) {

		var i_self = this;

		var o_properties = i_selected.get("properties");
		var o_clone = Ext.code(o_properties);

		var i_pnlPreview = i_self.getPreviewPanel();

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

			delete o_clone.itemId;
			delete o_clone.nodeType;
			delete o_clone.group;
			delete o_clone.index;
			delete o_clone.entityClass;
			delete o_clone.contentRoot;
			delete o_clone.name;
			delete o_clone.uiLayout;
			delete o_clone.extended;

			var o_config = o_properties.config || {};
			var s_class = o_properties.main || "";
			var o_paths = o_properties.path || {};

			if (s_class) {

				i_pnlPreview.removeAll(true);

				if (!Ext.Object.isEmpty(o_paths)) {
					Ext.Loader.setConfig(o_paths);
				}

				var i_component = Ext.create(s_class, o_config);

				i_pnlPreview.add([
					i_component
				]);

				i_pnlPreview.show();
			}
		}
	},

	createGroupConfig: function (o_properties) {

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

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

		return o_group;
	},

	createLayoutConfig: function (o_properties) {

		var o_layout = {
			itemId: o_properties.layoutType + "-" + ip2.unique(),
			leaf: false,
			expanded: false,
			allowDrop: o_properties.layoutType == "border" ? false : true,
			allowDrag: true,
			properties: {
				nodeType: "layout",
				name: o_properties.layoutType,
				padding: 10,
				layout: o_properties.layout
			}
		};

		return o_layout;
	}

});
