Ext.define("Ext.ux.history.view.HistoryPanel", {
	extend: "Ext.panel.Panel",
	alias: ["widget.historypanel"],
	controller: "history",
	requires: [
		"Ext.ux.history.controller.History",
		"Ext.ux.util.ace.DiffPanel",
	],
	border: false,
	layout: "anchor",
	autoScroll: true,
	bodyPadding: 2,
	bodyStyle: {
		background: "#e4e6e9"
	},
	header: {
		height: 31,
		style: {
			background: "#e0e3e6"
		}
	},
	config: {
		titleTemplate: null,
		util: null
	},
	listeners: {
		gridrowselect: {
			fn: function(i_grid, i_record) {

				var i_self = this;
				Ext.suspendLayouts();
				i_self.buildPanel(i_record);
				Ext.resumeLayouts(true);
			}
		}
	},
	initComponent: function() {

		var i_self = this;
		i_self.language = ip2.getUserLanguageCode();

		i_self.callParent();
		i_self.createTemplate();

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

		return i_self;
	},

	buildPanel: function(i_record) {

		var i_self = this;
		var i_controller = i_self.getController();
		var a_items = [];

		i_self.removeAll();

		var i_tiltel = i_self.addRow(
			ip2.i18n({
				da: "<strong>Feltnavn</strong>",
				en: "<strong>Field Name</strong>"
			}),
			ip2.i18n({
				da: "<strong>Ændret fra</strong>",
				en: "<strong>Changed From</strong>"
			}),
			ip2.i18n({
				da: "<strong>Ændret til</strong>",
				en: "<strong>Changed To</strong>"
			}),
			false
		);

		a_items.push(i_tiltel);

		// set header title
		var s_title = i_self.getTitleValue(i_record);
		i_self.setTitle(s_title);

		var o_entity = i_controller.getDmdEntityByEntityName(i_record.get("LOGENT"));

		// find all objects in record
		var o_logRow = Ext.decode(i_record.get("LOGROW"), true) || {};
		var o_prevRow = Ext.decode(i_record.get("PREVROW"), true) || {};

		if (!Ext.isObject(o_logRow)) {
			o_logRow = {
				value: o_logRow
			};
		}

		if (!Ext.isObject(o_prevRow)) {
			o_prevRow = {
				value: o_prevRow
			};
		}

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

			var i_entry;
			var o_result;

			value = value || "";
			var prevValue = o_prevRow[s_key] || "";

			if (Ext.String.startsWith(value, "{")) {

				var o_from = Ext.decode(o_prevRow[s_key], true) || {};
				var o_to = Ext.decode(value, true) || {};

				o_result = i_self.checkObjectDifferences(o_from, o_to);

				if (o_result.from.length > 0 || o_result.to.length > 0) {

					s_title = i_self.getFieldLabelTitle(o_entity, s_key) || s_key;

					i_entry = i_self.addEntry(o_result, s_title);
					a_items.push(i_entry);
				}
			}
			else if (Ext.isArray(value)) {

				o_result = i_self.checkArrayDifferences(prevValue, value);

				if (o_result.from.length > 0 || o_result.to.length > 0) {

					s_title = i_self.getFieldLabelTitle(o_entity, s_key) || s_key;

					i_entry = i_self.addEntry(o_result, s_title);
					a_items.push(i_entry);
				}
			}
			else if (Ext.isObject(value)) {

				o_result = i_self.checkObjectDifferences(prevValue, value);

				if (o_result.from.length > 0 || o_result.to.length > 0) {

					s_title = i_self.getFieldLabelTitle(o_entity, s_key) || s_key;

					i_entry = i_self.addEntry(o_result, s_title);
					a_items.push(i_entry);
				}
			}
			else {
				if (prevValue != value) {

					var b_html = false;

					if (String(prevValue).toLowerCase().indexOf("<html>") > 0 ||
						String(value).toLowerCase().indexOf("<html>") > 0) {
						b_html = true;
					}

					i_entry = i_self.addRow(
						i_self.getFieldLabelTitle(o_entity, s_key) || s_key,
						prevValue,
						value,
						true,
						o_entity,
						s_key,
						b_html
					);

					a_items.push(i_entry);
				}
			}
		});

		i_self.add(a_items);
	},

	checkArrayDifferences: function(a_fromArray, a_toArray) {

		var i_self = this;

		a_fromArray = a_fromArray || [];
		a_toArray = a_toArray || [];

		var a_from = [];
		var a_to = [];

		var o_array = {
			from: [],
			to: []
		};

		var o_object = {
			from: [],
			to: []
		};

		Ext.Array.each(a_toArray, function(value_to, n_index) {

			var value_from = a_fromArray[n_index] || "";
			var o_result;

			value_to = value_to || "";

			if (Ext.isArray(value_to)) {

				o_result = i_self.checkArrayDifferences(value_from, value_to);
				Ext.Object.merge(o_object, o_result);
			}
			else if (Ext.isObject(value_to)) {

				o_result = i_self.checkObjectDifferences(value_from, value_to);
				Ext.Object.merge(o_object, o_result);
			}
			else {
				if (value_from != value_to) {

					a_from.push({
						flex: 1,
						value: value_from
					});

					a_to.push({
						flex: 1,
						value: value_to
					});
				}
			}
		});

		a_from = a_from.concat(o_array.from);
		a_to = a_to.concat(o_array.to);

		a_from = a_from.concat(o_object.from);
		a_to = a_to.concat(o_object.to);

		return Ext.apply({}, {
			from: a_from,
			to: a_to
		});
	},

	checkObjectDifferences: function(o_from, o_to) {

		var i_self = this;

		o_from = o_from || {};
		o_to = o_to || {};

		var a_from = [];
		var a_to = [];

		var o_array = {
			from: [],
			to: []
		};

		var o_object = {
			from: [],
			to: []
		};

		var s_valueFrom = Ext.encode(o_from);
		var s_valueTo = Ext.encode(o_to);

		if (s_valueFrom !== s_valueTo) {
			a_from.push({
				value: o_from
			});

			a_to.push({
				value: o_to
			});
		}

		a_from = a_from.concat(o_array.from);
		a_to = a_to.concat(o_array.to);

		a_from = a_from.concat(o_object.from);
		a_to = a_to.concat(o_object.to);

		return Ext.apply({}, {
			from: a_from,
			to: a_to
		});
	},

	addRow: function(s_title, s_fromValue, s_toValue, b_ecsapce, o_entity, s_property, b_html) {

		var i_self = this;

		var a_items = [];

		a_items.push({
			xtype: "displayfield",
			width: 160,
			value: s_title
		});

		if (!s_property || b_html) {

			if (b_html) {

				var s_mode = "html";

				if (s_property) {

					var o_field = i_self.getPropertyFromEntity(o_entity, s_property);

					var i_util = i_self.getUtil();
					var o_uirules = ip2.uirules;

					var o_collection;
					var b_found = false;
					var s_type = o_field.type || "varchar";

					while (!b_found) {
						var o_current = o_uirules.collections[s_type];

						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;

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

					var o_component = o_components[s_property];

					if (o_component) {
						s_mode = o_component.mode || "html";
					}
				}

				var i_diffpanel = Ext.widget("ux.util.ace.diffpanel", {
					mode: s_mode,
					flex: 1,
					maxHeight: 500,
					leftValue: s_fromValue,
					rightValue: s_toValue
				});

				a_items.push(i_diffpanel);
			}
			else {
				a_items.push({
					flex: 1,
					value: s_fromValue
				});

				a_items.push({
					flex: 1,
					value: s_toValue
				});
			}
		}
		else {
			var o_field = i_self.getPropertyFromEntity(o_entity, s_property);

			if (o_field) {

				var i_util = i_self.getUtil();
				var o_uirules = ip2.uirules;

				var o_collection;
				var b_found = false;
				var s_type = o_field.type || "varchar";

				while (!b_found) {
					var o_current = o_uirules.collections[s_type];

					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;

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

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

					delete o_value.name;

					o_value.flex = 1;
					o_value.value = s_fromValue;
					o_value.disabled = true;
					o_value.typeAhead = false;

					try {
						var i_from = Ext.create(o_value.uiclass, o_value);

						o_value.value = s_toValue;

						var i_to = Ext.create(o_value.uiclass, o_value);

						delete i_from.fieldLabel;
						delete i_to.fieldLabel;

						a_items.push(i_from);
						a_items.push(i_to);
					}
					catch (o_err) {}
				});
			}
			else {
				a_items.push({
					flex: 1,
					value: s_fromValue
				});

				a_items.push({
					flex: 1,
					value: s_toValue
				});
			}
		}

		var i_row = Ext.widget("fieldcontainer", {
			layout: "hbox",
			hideLabel: true,
			style: {
				"margin-bottom": "1px"
			},
			defaults: {
				xtype: "displayfield",
				htmlEncode: b_ecsapce,
				style: {
					"background": "#ffffff",
					"padding-left": "4px",
					"border-style": "solid",
					"border-width": "1px",
					"border-color": "#e4e6e9"
				}
			},
			items: a_items
		});

		return i_row;
	},

	addEntry: function(o_result, s_title) {

		var a_items = [];

		var o_toValue = o_result.to[0];
		var o_fromValue = o_result.from[0];

		var i_diffpanel = Ext.widget("ux.util.ace.diffpanel", {
			mode: "json",
			flex: 1,
			maxHeight: 500,
			leftValue: JSON.stringify(o_fromValue, null, 4, 4),
			rightValue: JSON.stringify(o_toValue, null, 4, 4)
		});

		a_items.push({
			xtype: "displayfield",
			width: 160,
			value: s_title
		});

		a_items.push(i_diffpanel);

		var i_entry = Ext.widget("fieldcontainer", {
			layout: {
				type: "hbox",
				align: "stretch"
			},
			style: {
				"margin-bottom": "1px"
			},
			defaults: {
				style: {
					"background": "#ffffff",
					"padding-left": "4px",
					"border-style": "solid",
					"border-width": "1px",
					"border-color": "#e4e6e9"
				}
			},
			items: a_items
		});

		return i_entry;
	},

	getFieldLabelTitle: function(o_entity, s_property) {

		var i_self = this;

		var s_title = "";

		if (o_entity) {

			var o_form = o_entity.ui.forms.portfolio;
			var o_columns = o_entity.columns;
			var a_xpdFields = [];
			var a_xpds = [];

			var o_item = o_form.items || {};
			var a_fields = o_item.columns || [];

			Ext.Object.each(o_columns, function(s_key, o_value) {

				if (o_value.hasOwnProperty("xpd")) {
					a_xpdFields.push(o_value.xpd + ".xpd");
				}
			});

			Ext.Array.each(a_xpdFields, function(s_xpd) {

				var o_xpd = ip2.resource.get(s_xpd);
				a_xpds.push(o_xpd);
			});

			var o_field;

			Ext.Array.each(a_fields, function(o_value) {
				if (o_value.name == s_property) {
					o_field = o_value;
					return false;
				}
			});

			if (a_xpds.length > 0) {

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

					var o_properties = o_value.properties;
					var o_property;

					Ext.Object.each(o_properties, function(s_key, o_field) {

						if (s_key === s_property) {
							o_property = o_field;
							return false;
						}
						else {
							if (o_field.from && Ext.isObject(o_field.from)) {
								if (o_field.from.field === s_property) {
									o_property = o_field;
									return false;
								}
							}
						}
					});

					if (!o_property) {

						Ext.Object.each(o_value.collections, function(s_collection, o_collection) {

							var o_collectionProperties = o_collection.properties || {};

							Ext.Object.each(o_collectionProperties, function(s_key, o_field) {
								if (s_key === s_property) {
									o_property = o_field;
									return false;
								}
								else {
									if (o_field.from && Ext.isObject(o_field.from)) {
										if (o_field.from.field === s_property) {
											o_property = o_field;
											return false;
										}
									}
								}
							});

							if (o_property) {
								return false;
							}
						});
					}
					if (o_property) {
						s_title = ip2.xpd.translate(o_value, o_property.title, i_self.language);
						return false;
					}
				});
			}
			else {
				if (o_field) {
					s_title = ip2.i18n(o_field.title);
				}
			}
		}

		return s_title;
	},

	getPropertyFromEntity: function(o_entity, s_property) {

		var o_field = null;

		if (o_entity) {

			var o_form = o_entity.ui.forms.portfolio;
			var o_columns = o_entity.columns;
			var a_xpdFields = [];
			var a_xpds = [];

			var a_fields = o_form.items || [];

			Ext.Array.each(o_columns, function(s_key, o_value) {

				if (o_value.hasOwnProperty("xpd")) {
					a_xpdFields.push(o_value.xpd + ".xpd");
				}
			});

			Ext.Array.each(a_xpdFields, function(s_xpd) {

				var o_xpd = ip2.resource.get(s_xpd);
				a_xpds.push(o_xpd);
			});

			Ext.Array.each(a_fields, function(o_value) {
				if (o_value.name == s_property) {
					o_field = o_value;
					return false;
				}
			});

			if (a_xpds.length > 0) {

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

					var o_properties = o_value.properties;
					var o_property;

					Ext.Object.each(o_properties, function(s_key, o_field) {

						if (s_key === s_property) {
							o_property = o_field;
							return false;
						}
						else {
							if (o_field.from && Ext.isObject(o_field.from)) {
								if (o_field.from.field === s_property) {
									o_property = o_field;
									return false;
								}
							}
						}
					});

					if (!o_property) {

						Ext.Object.each(o_value.collections, function(s_collection, o_collection) {

							var o_collectionProperties = o_collection.properties || {};

							Ext.Object.each(o_collectionProperties, function(s_key, o_field) {
								if (s_key === s_property) {
									o_property = o_field;
									return false;
								}
								else {
									if (o_field.from && Ext.isObject(o_field.from)) {
										if (o_field.from.field === s_property) {
											o_property = o_field;
											return false;
										}
									}
								}
							});

							if (o_property) {
								return false;
							}
						});
					}
					if (o_property) {
						o_field = o_property;
						return false;
					}
				});
			}
		}

		return o_field;
	},

	createTemplate: function() {

		var i_self = this;
		var i_controller = i_self.getController();

		var i_template = Ext.create("Ext.XTemplate",
			"<tpl for=\".\">",
				"<strong>",
					"<span>ID: {ID}</span>&nbsp",
					"<span>" + ip2.i18n({
						da: "Ændret af: ",
						en: "Changed by: "
					}) + "{USRNAM}</span>&nbsp",
					"<span>" + ip2.i18n({
						da: " d. ",
						en: " on "
					}) + "{[this.renderer(values.LOGTS)]}</span>",
				"</strong>",
			"</tpl>",
			{
				renderer: function(value) {

					return i_controller.formatTimestamp(value);
				}
			}
		);

		i_template.compile();
		i_self.setTitleTemplate(i_template);
	},

	getTitleValue: function(i_record) {

		var i_self = this;
		var i_controller = i_self.getController();
		var i_template = i_self.getTitleTemplate();

		var o_values = i_record.getData();

		var s_entity = i_record.get("LOGENT");

		if (s_entity) {
			var o_entity = i_controller.getDmdEntityByEntityName(i_record.get("LOGENT"));

			var i_model = ip2.model({
				dmd: o_entity.dmd,
				entityName: o_entity.name,
				uiName: "portfolio",
				context: "form"
			});

			var o_logRow = Ext.decode(i_record.get("LOGROW"), true) || {};

			o_values = {
				ID: o_logRow[i_model.idProperty],
				USRNAM: i_record.get("USRNAM"),
				LOGST: i_record.get("LOGTS")
			};
		}

		return i_template.apply(o_values);
	}

});
