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

	extend: "Ext.grid.Panel",

	alias: [
		"widget.ip2DomainModelEntityRelationGrid"
	],
	border: 0,

	height: 150,

	autoScroll: true,

	model: "",

	requires: [
		"Portfolio.designer.ui.domainModelCardinalityComboBox",
		"Portfolio.designer.model.domainModelEntityRelationManagerDataModel",
		"Portfolio.designer.ui.domainModelEntityRelationRowProperties"
	],

	config: {
		entityManager: null,
		entity: null,
		entityName: "",
		designer: null,
		model: null,
		required: false,
		record: null,
		selector: null,
		relationAs: null
	},

	initComponent: function() {

		var i_self = this;
		var i_designer = i_self.getDesigner();
		var o_model = i_self.getModel() || i_designer.model;
		var a_entities = o_model.required;

		i_self.relationAs = i_designer.entities;

		i_self.columns = i_self.createColumns(a_entities);
		i_self.store = i_self.createStore();

		// grid plugins (cell editor)

		var i_plugin = Ext.create("Ext.grid.plugin.CellEditing", {
			pluginId: "celledit",
			clicksToEdit: 1,
			listeners: {
				beforeedit: {
					fn: function() {
						return !i_self.getRequired();
					}
				},
				edit: {
					fn: function(i_editor, i_context) {

						var i_record = i_context.record;
						var i_selector = i_self.getSelector();
						var s_field = i_context.field;

						i_record.commit();

						if (i_record.get("betweenOccur") == "many" && i_record.get("andOccur") == "many") {
							i_selector.hide();
						}
						else {
							if (s_field == "andEntity") {
								i_selector.setAndRelation(i_record.get("andEntity"), i_record.get("andOn"));
								i_selector.show();
							}
						}

						if (i_record.get("betweenEntity") && i_record.get("andEntity") && i_record.get("cardinality")) {

							var a_betweenOn = i_record.get("betweenOn") || [];
							var a_andOn = i_record.get("andOn") || [];

							if (a_betweenOn.length > 0 && a_andOn.length > 0) {
								i_self.fireEvent("removeRelation", i_record.get("andEntity"));
								i_self.fireEvent("updateRelation", i_record);
							}
						}
					}
				}
			}
		});

		i_self.plugins = i_plugin;

		// toolbar
		i_self.tbar = [
			{
				xtype: "button",
				text: ip2.i18n("addNew"),
				iconCls: "pf-add",
				disabled: i_self.getRequired(),
				handler: function() {

					var i_store = i_self.getStore();
					var i_model = i_store.getModel();
					var i_record = i_model.create({});

					var o_properties = {
						shownAsChild: {
							between: false,
							and: false
						}
					};

					var i_entityManager = i_self.getEntityManager();
					var i_propertyManger = i_entityManager.getEntityPropertyManager();

					i_record.set("betweenEntity", i_propertyManger.getForm().findField("name").getValue());
					i_record.set("andEntity", "");
					i_record.set("properties", o_properties);

					i_store.loadData([i_record], true);

					i_self.getSelectionModel().select(i_record);

					var i_plugin = i_self.getPlugin("celledit");

					i_plugin.startEditByPosition({
						row: i_store.count() - 1,
						column: 0
					});
				}
			}
		];

		i_self.callParent();

		i_self.on({
			select: {
				fn: function(view, i_record, n_index) {

					i_self.setRecord(i_record);
					var i_selector = i_self.getSelector();

					if (i_record.get("betweenOccur") == "many" && i_record.get("andOccur") == "many") {
						i_self.selector.hide();
					}
					else {

						var i_entityManager = i_self.getEntityManager();
						var i_columnManager = i_entityManager.getColumnManager();
						var i_columnGrid = i_columnManager.getColumnGrid();
						var i_store = i_columnGrid.getStore();
						var a_rows = i_store.getRange();

						var a_colums = [];

						Ext.Array.each(a_rows, function(i_record) {
							a_colums.push(i_record.data);
						});

						var o_value = {
							columns: a_colums
						};

						i_selector.setBetweenRelation(i_record.get("betweenEntity"), i_record.get("betweenOn"), a_colums);
						i_selector.setAndRelation(i_record.get("andEntity"), i_record.get("andOn"));
						i_selector.show();
					}
				}
			},
			itemcontextmenu: {
				fn: function(i_view, i_record, i_item, n_index, i_event) {
					i_event.stopEvent();

					i_view.getSelectionModel().select(n_index);

					var a_coords = i_event.getXY();

					var i_menu = Ext.create("Ext.menu.Menu", {
						items: [
							{
								xtype: "menuitem",
								text: ip2.i18n("properties"),
								iconCls: "pf-gearwheel",
								disabled: i_self.getRequired(),
								handler: function() {
									i_self.rowProperties();
								}
							},
							{
								xtype: "menuitem",
								text: ip2.i18n("delete"),
								iconCls: "pf-delete",
								disabled: i_self.getRequired(),
								handler: function() {
									i_self.deleteRow();
								}
							}
						]
					});

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

		i_self.enableBubble("updateRelation");
		i_self.enableBubble("removeRelation");
	},

	createColumns: function(a_entities) {

		var i_self = this;

		var a_colums = [
			{
				header: ip2.i18n("between"),
				dataIndex: "betweenEntity",
				flex: 1,
				renderer: i_self.betweenEntityName
			},
			{
				header: ip2.i18n("onFields"),
				dataIndex: "betweenOn",
				flex: 2,
				renderer: i_self.onArrayBetweenRenderer
			},
			{
				header: ip2.i18n("cardinality"),
				dataIndex: "cardinality",
				renderer: i_self.cardinalityRenderer,
				width: 70,
				align: "center",
				editor: {
					xtype: "ip2DomainModelCardinalityComboBox",
					editable: false,
					listeners: {
						select: function(i_field, i_record) {

							var i_selector = i_self.getSelector();

							var value = i_record.get("value");
							var i_selected = i_self.getRecord();

							i_selected.set("andOccur", value.substr(value.indexOf("2") + 1));
							i_selected.set("betweenOccur", value.substr(0, value.indexOf("2")));
							i_selected.set("cardinality", value);

							if (value == "many2many") {
								i_selector.hide();
							}
							else {
								i_selector.show();
							}
						}
					}
				}
			},
			{
				header: ip2.i18n("and"),
				dataIndex: "andEntity",
				flex: 1,
				renderer: i_self.getEntityName(),
				editor: {
					xtype: "ip2DomainModelEntityComboBox",
					queryMode: "local",
					entities: a_entities
				}
			},
			{
				header: ip2.i18n("onFields"),
				dataIndex: "andOn",
				flex: 2,
				renderer: i_self.onArrayAndRenderer
			},
			{
				header: ip2.i18n("as"),
				dataIndex: "properties",
				renderer: i_self.asRenderer
			}
		];

		return a_colums;
	},

	createStore: function() {

		var i_self = this;
		var o_entity = i_self.getEntity();
		var i_designer = i_self.getDesigner();
		var o_model = i_self.getModel() || i_designer.model;
		var a_entities = o_model.required;

		var a_relations = [];

		Ext.Array.each(o_model.relations, function(o_relation) {

			var o_result;

			var s_entity = o_relation.between.entity == o_entity.name ? o_relation.between.entity : o_relation.and.entity;
			var b_and = o_relation.and.entity == o_entity.name ? true : false;

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

				if (o_found) {

					if (b_and) {
						o_result = Ext.apply({}, {
							between: Ext.clone(o_relation.and),
							and: Ext.clone(o_relation.between),
							properties: Ext.clone(o_relation.properties),
							cid: o_relation.cid
						});
					}
					else {
						o_result = o_relation;
					}
				}

				if (o_result) {
					var o_temp = Ext.Array.findBy(a_relations, function(o_config) {
						return o_config.between.entity == o_result.between.entity && o_config.and.entity == o_result.and.entity;
					});

					if (!o_temp) {
						a_relations.push(o_result);
					}
				}
			}
		});

		var o_data = {
			relations: a_relations
		};

		var i_store = Ext.create("Ext.data.Store", {
			model: "Portfolio.designer.model.domainModelEntityRelationManagerDataModel",
			data: o_data,
			proxy: {
				type: "memory",
				reader: {
					type: "json",
					rootProperty: "relations"
				}
			}
		});

		return i_store;
	},

	betweenEntityName: function(s_name, meta, i_record) {

		var i_self = this;
		var i_designer = i_self.getDesigner();
		var o_model = i_designer.model;
		var a_entities = o_model.required;
		var s_title = s_name;

		if (i_record.get("properties")) {

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

			if (o_entity) {
				s_title = ip2.i18n(o_entity.title);
			}

			return "<img src=\"/system/shared/collection/icons/16x16/plain/gear.png\" width=\"10\" height=\"10\" />&nbsp;" +
			s_title;
		}
		else {
			return s_title;
		}
	},

	entityName: function(name) {

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

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

		if (o_entity) {
			s_title = ip2.i18n(o_entity.title);
		}

		return s_title;
	},

	cardinalityRenderer: function(value, meta, record) {
		if (value.length < 2) {
			return "";
		}
		return "<img src=\"/portfolio/styles/icon/flatui/designer/" + value + ".png\" border=\"0\" width=\"13\" height=\"13\" />";
	},

	onArrayBetweenRenderer: function(a_value, i_meta, i_record, n_row, n_col) {

		var i_self = this;
		var i_model = i_self.getModel();
		var s_between = i_record.get("betweenEntity");
		var a_required = i_model.required;

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

		if (!Ext.isArray(a_value)) {
			return "";
		}

		var a_join = [];

		o_entity = o_entity || {
			columns: []
		};

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

			var s_value = o_value;

			if (Ext.isObject(o_value)) {

				Ext.Array.each(o_entity.columns, function(o_column) {
					if (o_column.name === o_value.name) {
						a_join.push(o_column.name + " (" + ip2.i18n(o_column.title) + ")");
					}
				});
			}
			else {
				a_join.push(s_value);
			}
		});

		return a_join.join(", ");
	},

	onArrayAndRenderer: function(a_value, i_meta, i_record, n_row, n_col) {

		var i_self = this;
		var i_model = i_self.getModel();
		var s_between = i_record.get("andEntity");
		var a_required = i_model.required;

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

		if (!Ext.isArray(a_value)) {
			return "";
		}

		var a_join = [];

		o_entity = o_entity || {
			columns: []
		};

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

			var s_value = o_value;

			if (Ext.isObject(o_value)) {
				Ext.Array.each(o_entity.columns, function(o_column) {
					if (o_column.name === o_value.name) {
						a_join.push(o_column.name + " (" + ip2.i18n(o_column.title) + ")");
					}
				});
			}
			else {
				a_join.push(s_value);
			}
		});

		return a_join.join(", ");
	},

	asRenderer: function(o_properties) {

		if (Ext.isEmpty(o_properties)) {
			return "";
		}

		var n_index = Ext.Array.indexOf(this.relationAs, o_properties.as);
		if (n_index == -1) {
			this.relationAs.push(o_properties.as);
		}
		return o_properties.as;
	},
	setAs: function(newValue, oldValue) {

		var i_self = this;
		var i_record = i_self.getRecord();
		var title = newValue;

		// replace special characters with underscore
		newValue = newValue.replace(/[^a-zA-Z0-9]/g, "_");

		var cnt = 0;
		var as_ = newValue;
		while (i_self.checkAsAlreadyExists(as_)) {
			as_ = as_ + "_" + cnt++;
		}
		if (oldValue) {
			var index = Ext.Array.indexOf(i_self.relationAs, oldValue);
			if (index == -1) {
				i_self.relationAs.push(as_);
			}
			else {
				Ext.Array.replace(i_self.relationAs, index, 1, [as_]);
			}
		}
		else {
			i_self.relationAs.push(as_);
		}

		var o_properties = i_record.get("properties");
		o_properties.as = as_;
		o_properties.title = title;
		i_record.set("properties", o_properties);
	},
	checkAsAlreadyExists: function(as) {
		return (Ext.Array.indexOf(this.relationAs, as) == -1) ? false : true;
	},
	getAsTitle: function(as) {
		var title = "";
		var store = this.getStore();
		store.each(function(record, index, count) {

			var o_properties = record.get("properties") || {};
			if (o_properties.as == as) {
				title = record.get("properties").title;
				return false;
			}
		});
		return title;
	},
	getAsFrom: function(as, relatedEntity) {
		var from = "";
		var store = this.getStore();
		store.each(function(record, index, count) {

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

			if (o_properties.as == as) {
				if (record.get("betweenEntity") == relatedEntity) {
					from = record.get("and").entity;
				}
				else {
					from = record.get("andEntity");
				}
				return false;
			}
		});
		return from;
	},
	deleteRow: function() {

		var i_self = this;

		var a_records = i_self.getSelectionModel().getSelection();
		var i_record = a_records[0];

		ip2.messageBox({
			title: ip2.i18n("confirmDeleteTitle"),
			message: ip2.i18n("confirmDelete"),
			yesFn: function () {
				var a_records = i_self.getSelectionModel().getSelection();
				var i_entityManager = i_self.getEntityManager();

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

					var s_entity = i_record.get("betweenEntity") != i_self.entity.name ?
						i_record.get("betweenEntity") : i_record.get("andEntity");

					if (s_entity && i_entityManager.getFormDesigner() && i_entityManager.getViewManager()) {

						i_self.fireEvent("removeRelation", s_entity);
					}
				});

				i_self.store.remove(i_record);
				i_self.getSelectionModel().select(0);
			},
			yesText: ip2.i18n({
				da: "Ok",
				en: "OK"
			}),
			cancelText: ip2.i18n({
				da: "Annuller",
				en: "Cancel"
			})
		});
	},

	rowProperties: function() {
		var i_self = this;

		var i_window = Ext.create("Portfolio.designer.ui.domainModelEntityRelationRowProperties", {
			record: i_self.getSelectionModel().getSelection()[0],
			designer: i_self.getDesigner(),
			entityManager: i_self.getEntityManager(),
			relationGrid: i_self,
			listeners: {
				notifyRelationUpdate: {
					fn: function(i_record) {
						i_self.fireEvent("updateRelation", i_record);
					}
				}
			}
		});

		i_window.show();
	}
  });
