Ext.define("Portfolio.entity.view.Tree", {
	extend: "Ext.tree.Panel",

	xtype: "portfolio-entity-tree",

	alternateClassName: [
		"Ext.ux.entity.Tree"
	],

	alias: [
		"widget.ux.entity.tree",
		"widget.portfolio.entity.tree"
	],

	config: {
		dmd: null,
		entity: null,
		viewName: null,
		context: "grid",
		model: null,
		parentID: "",
		childID: "",
		textProperty: "",
		sequence: "",
		actionBar: null,
		filterBar: null,
		dmdName: "",
		allowEdit: true,
		allowAdd: true,
		allowLink: true,
		allowFilter: true,
		allowSearch: true,
		allowExport: true,
		allowDelete: true,
		showBreadcrumb: false,
		autoLoad: true,
		breadcrumbBar: null,
		searchCombo: true
	},

	useArrows: true,

	defaultRootId: "id",

	requires: [
		"Portfolio.entity.store.Tree",
		"Portfolio.entity.util.Toolbar"
	],

	initComponent: function() {

		var i_self = this;
		i_self.initializeDefaults();
		var i_model = i_self.createModel();
		var a_columns = i_self.createColumns();
		i_self.columns = a_columns;

		i_self.idProperty = i_self.defaultRootId = i_model.idProperty;

		i_self.store = i_self.createStore();

		if (i_self.getSequence()) {
			i_self.viewConfig = i_self.createViewConfig();
		}

		i_self.callParent();

		i_self.addDocked(i_self.createActionBar());
		i_self.addDocked(i_self.createFilterBar());

		if (i_self.getShowBreadcrumb()) {
			i_self.addDocked(i_self.createBreadCrumbBar());
		}

		i_self.on({
			sortchange: {
				fn: function(i_header, i_column, s_direction) {
					if (i_self.getFilterBar()) {
						i_self.getFilterBar().sortChange(i_column);
					}
				},
				buffer: 10
			},
			itemclick: {
				fn: function(i_view, i_selected) {

					if (i_self.getShowBreadcrumb()) {
						var i_toolbar = i_self.getBreadcrumbBar();
						if (i_toolbar) {
							i_toolbar._needsSync = true;
							i_toolbar.updateSelection(i_selected);
							i_toolbar._needsSync = false;
						}
					}
				}
			},
			itemcontextmenu: {
				fn: function(i_view, i_node, i_item, n_index, i_event) {

					i_event.preventDefault();

					var a_coords = i_event.getXY();
					var a_items = i_self.getMenuItems(i_node, i_self.getAllowAdd(), i_self.getAllowEdit(), i_self.getAllowDelete());

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

					i_menu.showAt(a_coords[0], a_coords[1]);
				}

			},
			afterFilter: {
				fn: function (i_filterbar, n_filters) {

					var i_self = this;
					var i_toolbar = i_self.getActionBar();
					i_toolbar.fireEvent("afterfilter", n_filters);
				}
			}
		});

		var o_config = i_self.getModelConfig();;

		var i_store = i_self.getStore();

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

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

			if (i_selected) {

				var i_parent = i_selected.isRoot() ? i_selected : i_selected.parentNode;

				if (i_selected.isRoot()) {

					var i_view = i_self.getView();

					if (i_view.body.dom) {
						i_view.body.translate(0, 0, 0);
					}

					if (i_view.bufferedRenderer) {
						i_view.bufferedRenderer.onStoreClear();
					}
				}

				if (i_parent) {
					i_parent.collapse();
					i_parent.removeAll(false);

					i_store.read({
						node: i_parent,
						callback: function(i_store) {
							i_parent.expand();
						}
					});
				}
			}
		});

		var i_header = i_self.headerCt;

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

						var i_toolbar = i_self.getFilterBar();

						if (i_toolbar) {
							var s_ddGroup = i_header.reorderer.dragZone.ddGroup;
							i_toolbar.dd.addDDGroup(s_ddGroup);
						}
					}
				},
				buffer: 100
			}
		});
	},

	initializeDefaults: function() {

		var i_self = this;

		var o_dmd = ip2.resource.get(i_self.getDmd());
		var o_model = o_dmd.model;

		var o_entity = Ext.Array.findBy(o_model.entities, function(o_value) {
			return o_value.name == i_self.getEntity();
		});

		var s_parenID = i_self.getParentID();
		var s_childID = i_self.getChildID();

		if (!s_parenID) {
			s_parenID = o_entity.parentID;
			i_self.setParentID(s_parenID);
		}

		if (!s_childID) {
			s_childID = o_entity.childID;
			i_self.setChildID(s_childID);
		}

		i_self.createModel();
	},

	getMenuItems: function(i_node, b_add, b_edit, b_delete) {

		var i_self = this;
		var i_store = i_self.getStore();
		var i_record = i_node;
		var i_model = i_self.getModel();
		var o_config = i_self.getModelConfig();
		var s_dmd = i_self.getDmdName();
		var s_entity = i_self.getEntity();
		var a_items = [];

		if (b_add && ip2.isAccessible("app." + s_dmd + ".data.create") ||
			ip2.isAccessible("app." + s_dmd + ".data." + s_entity + ".´create")) {

			var i_add = Ext.widget("menuitem", {
				text: ip2.i18n({
					da: "Tilføj",
					en: "Add"
				}),
				itemId: "icon-add",
				iconCls: "pf-add",
				handler: function (i_button) {

					var i_newRecord = i_model.create({});
					i_newRecord.set(i_self.getParentID(), i_record.get(i_self.getChildID()));

					var o_data = Ext.clone(o_config);

					Ext.apply(o_data, {
						keys: {},
						context: "form",
						data: i_newRecord.getData()
					});

					Portfolio.app.fireEvent("entityedit", o_data, "create");
				}
			});

			a_items.push(i_add);
		}

		if (!i_record.isRoot()) {
			if (b_edit && (ip2.isAccessible("app." + s_dmd + ".data.update") ||
				ip2.isAccessible("app." + s_dmd + ".data.read") ||
				ip2.isAccessible("app." + s_dmd + ".data." + s_entity + ".update") ||
				ip2.isAccessible("app." + s_dmd + ".data." + s_entity + ".read"))) {

				var i_edit = Ext.widget("menuitem", {
					text: ip2.i18n({
						da: "Rediger",
						en: "Edit"
					}),
					itemId: "item-edit",
					iconCls: "pf-edit",
					handler: function (i_button) {

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

						var o_clone = Ext.clone(o_config);

						var s_action = "update";

						var o_keys = {};

						if (i_record) {
							o_keys[i_record.idProperty] = i_record.get(i_record.idProperty);
						}
			
						Ext.apply(o_clone, {
							keys: o_keys
						});

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

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

								if (i_form) {
									Portfolio.app.fireEvent("entityWindow", o_clone, s_action);
								}
								else {
									Portfolio.app.fireEvent("entityedit", o_clone, s_action);
								}
							}
						}
					}
				});

				a_items.push(i_edit);
			}

			if (b_delete && ip2.isAccessible("app." + s_dmd + ".data.delete") ||
				ip2.isAccessible("app." + s_dmd + ".data." + s_entity + ".delete")) {

				var i_delete = Ext.widget("menuitem", {
					text: ip2.i18n({
						da: "Slet",
						en: "Delete"
					}),
					itemId: "itmDelete",
					iconCls: "pf-delete",
					handler: function () {

						i_self.deleteRecord(i_record, function() {

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

							var i_parent = i_selected.isRoot() ? i_selected : i_selected.parentNode;
							i_parent.collapse();
							i_parent.removeAll(false);

							i_store.read({
								node: i_parent,
								callback: function(i_store) {
									i_parent.expand();
								}
							});
						});
					}
				});
				a_items.push(i_delete);
			}
		}

		var i_refresh = Ext.widget("menuitem", {
			iconCls: "pf-refresh",
			text: ip2.i18n({
				da: "Opfrisk",
				en: "Refresh"
			}),
			handler: function() {

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

				i_selected.collapse();
				i_selected.removeAll(false);

				i_store.read({
					node: i_selected,
					callback: function(i_store) {
						i_selected.expand();
					}
				});
			}
		});

		a_items.push(i_refresh);

		return a_items;
	},

	createModel: function() {

		var i_self = this;
		var i_model = i_self.getModel();
		if (!i_model) {
			var o_config = Ext.apply({}, {
				dmd: i_self.getDmd(),
				entityName: i_self.getEntity(),
				uiName: i_self.getViewName(),
				context: i_self.getContext()
			});

			var s_dmdname = i_self.getDmd().split("/").pop().split(".").shift();

			i_model = ip2.model(o_config, null, true);

			i_self.setModel(i_model);
			i_self.setDmdName(s_dmdname);
		}

		return i_model;
	},

	createStore: function() {

		var i_self = this;

		var i_model = i_self.createModel();

		var i_root = i_self.root;

		var o_root = i_root || Ext.apply({}, {
			allowDrop: false,
			allowDrag: false,
			loaded: false
		});

		if (!i_root) {
			o_root[i_model.idProperty] = 0;

			o_root[i_self.getTextProperty()] = ip2.i18n({
				da: "...",
				en: "..."
			});
		}

		var i_store = Ext.create("Portfolio.entity.store.Tree", {
			model: i_model,
			dmd: i_self.getDmd(),
			entity: i_self.getEntity(),
			view: i_self.getViewName(),
			parentID: i_self.getParentID(),
			childID: i_self.getChildID(),
			root: o_root,
			idProperty: i_model.idProperty,
			remoteFilter: true,
			remoteSort: true,
			autoLoad: i_self.getAutoLoad(),
			sequence: i_self.getSequence(),
			listeners: {
				load: {
					fn: function(i_store, a_records) {

						if (i_self.getShowBreadcrumb()) {
							var i_toolbar = i_self.getBreadcrumbBar();
							if (i_toolbar) {
								var i_selectionModel = i_self.getSelectionModel();
								var a_selection = i_selectionModel.getSelection();
								if (a_selection.length > 0) {
									var i_selected = a_selection[0];
									i_toolbar._needsSync = true;
									i_toolbar.updateSelection(i_selected);
									i_toolbar._needsSync = false;
								}
							}
						}
					}
				}
			}
		});

		return i_store;
	},

	createColumns: function() {

		var i_self = this;
		var o_dmd = ip2.resource.get(i_self.getDmd());
		var o_model = o_dmd.model;
		var s_entity = i_self.getEntity();
		var s_view = i_self.getViewName();
		var a_viewColumns = [];
		var a_entityColumns = [];
		var a_result = [];

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

		if (o_entity) {

			Ext.Array.each(o_entity.columns, function(o_value) {
				var o_clone = Ext.clone(o_value);
				a_entityColumns.push(o_clone);
			});

			if (o_entity.ui.grids[s_view]) {

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

				var a_temp = Ext.Object.getValues(o_view.columns);

				Ext.Array.each(a_temp, function(o_value) {
					var o_clone = Ext.clone(o_value);
					a_viewColumns.push(o_clone);
				});
			}
		}

		var b_found = false;

		Ext.Array.each(a_viewColumns, function(o_viewColumn) {

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

			Ext.Array.each(a_entityColumns, function(o_entityColumn) {
				if (o_column.name == o_entityColumn.name) {
					Ext.apply(o_column, o_entityColumn);
					return false;
				}
			});

			if (!b_found && o_column.isTitle && !o_column.hide) {
				o_column.xtype = "treecolumn";
				b_found = true;
			}

			Ext.applyIf(o_column, {
				dataIndex: o_column.name,
				text: ip2.i18n(o_column.title) || o_column.name,
				flex: o_column.flex || 1,
				draggable: true,
				liveDrag: true
			});

			if (!o_column.hide) {
				a_result.push(o_column);
			}
		});

		if (!b_found && o_entity) {

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

				if (o_value.dataIndex == o_entity.idColumn) {
					o_value.xtype = "treecolumn";
				}
			});
		}

		return a_result;
	},

	getModelConfig: function() {

		var i_self = this;

		return {
			dmd: i_self.getDmd(),
			entityName: i_self.getEntity(),
			context: i_self.getContext(),
			uiName: i_self.getViewName()
		};
	},

	createActionBar: function() {

		var i_self = this;
		var i_store = i_self.getStore();
		var i_model = i_self.createModel();

		var i_toolbar = Ext.widget("entitytoolbar", {
			model: i_model,
			dmdInfo: i_self.getModelConfig(),
			store: i_store,
			grid: i_self,
			itemId: "maintoolbar",
			dock: "top",
			allowNew: false,
			hasExport: false,
			allowLink: i_self.getAllowLink(),
			allowSearch: i_self.getAllowSearch(),
			allowExport: i_self.getAllowExport(),
			allowFilter: i_self.getAllowFilter(),
			addMode: "form",
			searchCombo: i_self.getSearchCombo(),
			entityInfo: i_self.getEntityInfo(),
		});

		i_self.setActionBar(i_toolbar);
		return i_toolbar;
	},

	createFilterBar: function() {

		var i_self = this;
		var i_model = i_self.getModel();
		var s_dmd = i_self.getDmdName();
		var s_entity = i_self.getEntity();

		var b_allowMenu = (
			ip2.isAccessible("app." + s_dmd + ".functions.filter") ||
			ip2.isAccessible("app." + s_dmd + ".functions." + s_entity + ".filter.use")
		);

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

		i_self.setFilterBar(i_filterbar);

		return i_filterbar;
	},

	createBreadCrumbBar: function() {

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

		var i_toolbar = Ext.widget("breadcrumb", {
			dock: "top",
			store: i_store,
			showIcons: false,
			showMenuIcons: true,
			selection: i_store.getRoot(),
			displayField: i_self.getDisplayField(),
			listeners: {
				selectionchange: {
					fn: function(i_toolbar, i_selected) {
						i_self.setSelection(i_selected);
					}
				}
			}
		});

		i_self.setBreadcrumbBar(i_toolbar);

		return i_toolbar;
	},

	getDisplayField: function () {

		var i_self = this;
		var i_model = i_self.getModel();
		var a_columns = i_model.getFields() || i_self.columns;
		var s_field = "";

		Ext.Array.each(a_columns, function(o_column) {
			if (o_column.isTitle) {
				s_field = o_column.name;
				return false;
			}
		});

		return s_field;
	},

	deleteRecord: function (i_record, f_callback) {

		var i_self = this;

		var i_model = i_self.getModel();

		var s_question = ip2.i18n({
			da: "Ønsker du virkelig at slette?",
			en: "Do you really wish to delete?"
		});

		Ext.MessageBox.show({
			title: ip2.i18n({
				da: "Bekræft sletning",
				en: "Confirm deleting"
			}),
			msg: s_question,
			buttons: Ext.MessageBox.OKCANCEL,
			fn: function (btn) {

				if (btn == "ok") {

					var a_batch = [];
					var o_keys = {};

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

					a_batch.push({
						type: "delete",
						dmd: i_self.getDmd(),
						entity: i_self.getEntity(),
						key: o_keys
					});

					var s_message = ip2.i18n({
						da: "Sletter...",
						en: "Deleting..."
					});

					i_self.setLoading(s_message, true);

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

							i_self.setLoading(false);
							if (Ext.isFunction(f_callback)) {
								f_callback();
							}
						}
					});
				}
			}, icon: Ext.MessageBox.WARNING
		});
	},

	createViewConfig: function() {

		var i_self = this;

		var o_config = Ext.apply({}, {
			plugins: {
				ptype: "treeviewdragdrop",
				dropGroup: "entitytree",
				dragGroup: "entitytree",
				appendOnly: false,
				dropZone: {
					isValidDropPoint: function(i_node, s_position, i_dragZone, i_event, o_data) {

						var i_dropzone = this;
						var i_view = i_dropzone.view;
						var i_overRecord = i_view.getRecord(i_node);

						return s_position !== "append";
					}
				}
			},
			listeners: {
				beforedrop: {
					fn: function(i_node, o_data, i_overModel, s_dropPosition, i_dropHandler, e) {

						var i_store = i_self.getStore();
						var i_record = o_data.records[0];
						var s_sequnce = i_store.getSequence();

						var i_before = i_overModel.previousSibling;
						var i_after = i_overModel.nextSibling;

						var n_over = i_overModel.get(s_sequnce);
						var n_extra = 0;
						var n_sequnce;

						if (s_dropPosition === "before") {
							if (i_before) {
								n_extra = i_before.get(s_sequnce);
							}

							n_sequnce = ((n_extra + n_over) / 2);
						}
						if (s_dropPosition === "after") {
							if (i_after) {
								n_extra = i_after.get(s_sequnce);
							}
							else {
								n_extra = n_over + 1;
							}
							n_sequnce = ((n_over + n_extra) / 2);
						}

						i_record.set(s_sequnce, n_sequnce);
					}
				},
				drop: {
					fn: function(i_node, o_data, i_overModel, s_dropPosition, eOpts) {

						var i_record = o_data.records[0];
						i_self.upsertRecord(i_record);
					}
				}
			}
		});

		return o_config;
	},

	upsertRecord: function(i_record) {

		var i_self = this;
		var o_keys = {};

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

		var a_batch = [{
			type: "upsert",
			dmd: i_self.getDmd(),
			entity: i_self.getEntity(),
			key: o_keys,
			row: i_record.getData()
		}];

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

	getEntityInfo: function() {

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

		if (!o_entityInfo) {

			var o_config = Portfolio.util.Handler.dmd.getInfo({
				dmd: i_self.getDmd(),
				entity: i_self.getEntity(),
				context: "grid",
				view: i_self.getViewName()
			});
			i_self.entityInfo = o_entityInfo = o_config;
		}

		return o_entityInfo;
	}
});
