Ext.define("Portfolio.pd.util.Handler", {

	singleton: true,

	mixins: [
		"Ext.mixin.Mashup"
	],

	requiredScripts: [
        "/portfolio/app/pd/css/styles.css"
	],

	constructor: function (o_config) {

		var i_self = this;

		i_self.initConfig(o_config);

		return i_self;
	},

	processData: function(o_data, a_definition) {

		var i_self = this;

		var o_return = {};

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

			var o_result = {};

			var o_property = Ext.Array.findBy(a_definition, function (o_definition) {
				return o_definition.name == s_key && (o_definition.type == "collection" || o_definition.type == "group");
			});

			if (!o_property) {

				o_property = Ext.Array.findBy(a_definition, function (o_definition) {
					return o_definition.name == s_key;
				});
			}

			if (o_property) {

				if (o_property.type == "collection" || o_property.type == "group") {
					o_result = i_self.createCollection(o_property, a_definition,  value);
				}
				else {
					o_result = i_self.createProperty(o_property, a_definition, value);
				}

				o_return[s_key] = o_result;
			}
		});

		return o_return;

	},

	createCollection: function (o_collection, a_definition, o_data) {

		var i_self = this;

		var o_clone = Ext.clone(o_collection);

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

		if (a_extend.length > 0) {

			var a_recursion = i_self.getExtendedCollection(a_extend, a_definition);

			a_recursion.reverse();

			var o_merged = {};

			Ext.Array.each(a_recursion, function(o_extended){

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

					if (Ext.isPrimitive(value)) {
						o_merged[s_key] = value;
					}
					else {
						if (Ext.isArray(value)) {

							var a_temp = Ext.Array.from(o_merged[s_key]) || [];
							var a_value = Ext.Array.from(value);

							a_temp = Ext.Array.merge(a_temp, a_value);

							o_merged[s_key] = a_temp;
						}
						else{
							if (Ext.isObject(value)) {
								o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
							}
						}
					}

				});
			});

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

				if (Ext.isPrimitive(value)) {
					o_merged[s_key] = value;
				}
				else {
					if (Ext.isArray(value)) {

						var a_temp = Ext.Array.from(value) || [];
						var a_value = Ext.Array.from(o_merged[s_key]);

						a_temp = Ext.Array.merge(a_temp, a_value);

						o_merged[s_key] = a_temp;
					}
					else {
						if (Ext.isObject(value)) {
							o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
						}
					}
				}

			});

			o_clone = o_merged;

			delete o_clone.extend;

		}

		var a_items = Ext.Array.from(o_clone.items);

		var a_return = [];

		Ext.Array.each(a_items, function(item) {

			var o_property = item;

			if (Ext.isString(item)) {

				o_property = Ext.Array.findBy(a_definition, function (o_definition) {
					return o_definition.name == item && (o_definition.type == "collection" || o_definition.type == "group");
				});

				if (!o_property) {

					o_property = Ext.Array.findBy(a_definition, function (o_definition) {
						return o_definition.name == item;
					});
				}
			}

			if (o_property) {

				var value = o_data[o_property.name] || "";

				var o_rule = o_clone.rule || {};

				if (o_rule.apperence == "field") {
					var o_propRule = o_property.rule || {};

					Ext.apply(o_propRule, {
						prioritized: null
					});

					o_property.rule = o_propRule;
				}

				var o_output = i_self.createProperty(o_property, a_definition, value);

				a_return.push(o_output);
			}

		});

		var o_return = Ext.apply(o_clone, {
			items: a_return
		});

		var o_rule = o_clone.rule || {};

		o_rule = Ext.clone(o_rule);

		Ext.apply(o_clone, o_rule);

		delete o_clone.rule;

		o_return.apperence = o_return.apperence || "field";
		o_return.prioritized = o_data.hasOwnProperty("prioritized") ? o_data.prioritized :
								o_return.hasOwnProperty("prioritized") ? o_return.prioritized : null;

		return o_return;

	},

	createProperty: function (o_config, a_definition, value) {

		var i_self = this;

		var o_result = {};

		var o_clone = Ext.clone(o_config);

		if (o_clone.type == "collection" || o_clone.type == "group") {
			o_result = i_self.createCollection(o_clone, a_definition, value);
		}
		else {

			if (o_clone.extend) {

				var a_extended = i_self.getExtended(Ext.Array.from(o_clone.extend), a_definition);

				a_extended.reverse();

				var o_merged = {};

				Ext.Array.each(a_extended, function (o_extended) {

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

						if (Ext.isPrimitive(value)) {
							o_merged[s_key] = value;
						}
						else {
							if (Ext.isArray(value)) {

								var a_temp = Ext.Array.from(o_merged[s_key]) || [];
								var a_value = Ext.Array.from(value);

								a_temp = Ext.Array.merge(a_temp, a_value);

								o_merged[s_key] = a_temp;
							}
							else {
								if (Ext.isObject(value)) {
									o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
								}
							}
						}

					});
				});

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

					if (Ext.isPrimitive(value)) {
						o_merged[s_key] = value;
					}
					else {
						if (Ext.isArray(value)) {

							var a_temp = Ext.Array.from(o_merged[s_key]) || [];
							var a_value = Ext.Array.from(value);

							a_temp = Ext.Array.merge(a_temp, a_value);

							o_merged[s_key] = a_temp;
						}
						else {
							if (Ext.isObject(value)) {
								o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
							}
						}
					}

				});

				o_clone = o_merged;
				delete o_clone.extend;
			}

			var o_rule = o_clone.rule || {};

			o_rule = Ext.clone(o_rule);

			delete o_clone.rule;

			Ext.apply(o_clone, o_rule);

			Ext.apply(o_result, o_clone);

			i_self.processProperties(o_result);

			o_result.value = value;
			o_result.originalValue = value;
		}

		return o_result;
	},

	getExtended: function (a_values, a_definition) {

		var i_self = this;

		var a_return = [];

		Ext.Array.each(a_values, function(s_extend) {

			var o_property = Ext.Array.findBy(a_definition, function (o_definition) {
				return o_definition.name == s_extend || o_definition.name == s_extend &&
						(o_definition.type == "property");
			});

			if (o_property) {
				if (o_property.hasOwnProperty("extend") && !Ext.isEmpty(o_property.extend)) {

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

					var a_result = i_self.getExtended(a_extend, a_definition);

					a_return = a_return.concat(a_result);
					a_return.push(o_property);
				}
				else {
					a_return.push(o_property);
				}
			}
		});

		return a_return;
	},

	getExtendedCollection: function (a_values, a_definition) {

		var i_self = this;

		var a_return = [];

		Ext.Array.each(a_values, function(s_extend) {

			var o_property = Ext.Array.findBy(a_definition, function (o_definition) {
				return o_definition.id == s_extend || o_definition.name == s_extend &&
						(o_definition.type == "collection" || o_definition.type == "group");
			});

			if (o_property) {

				var o_clone = Ext.clone(o_property);

				var o_rule = o_clone.rule || {};

				Ext.apply(o_clone, o_rule);

				delete o_clone.rule;

				if (o_clone.hasOwnProperty("extend") && o_clone.extend) {

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

					var a_result = i_self.getExtended(a_extend, a_definition);

					a_return = a_return.concat(a_result);
					a_return.push(o_clone);
				}
				else {
					a_return.push(o_clone);
				}
			}
		});

		return a_return;
	},

	getExtendedFormCollection: function (a_values, a_definition) {

		var i_self = this;

		var a_return = [];

		Ext.Array.each(a_values, function(s_extend) {

			var o_property = Ext.Array.findBy(a_definition, function (o_definition) {
				return (o_definition.id == s_extend || o_definition.name == s_extend) && o_definition.type == "formCollection";
			});

			if (o_property) {

				var o_clone = Ext.clone(o_property);

				var o_rule = o_clone.rule || {};

				Ext.apply(o_clone, o_rule);

				delete o_clone.rule;

				if (o_clone.hasOwnProperty("extend") && !Ext.isEmpty(o_clone.extend)) {

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

					var a_result = i_self.getExtendedFormCollection(a_extend, a_definition);

					a_return = a_return.concat(a_result);

					a_return.push(o_clone);
				}
				else {
					a_return.push(o_clone);
				}
			}
		});

		return a_return;
	},

	processProperties: function(o_config) {

		var o_apply = {};

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

			switch (s_key) {
				case "dbtype":

					var s_type = value;

					var a_type = /\(\d*|[,.]*d\)/g.exec(value);
					var a_length = /\d+/g.exec(value);

					if (a_type) {

						s_type = value.substr(0, a_type.index);
					}

					Ext.apply(o_apply, {
						datatype: s_type,
					});

					if (a_length) {

						var n_end = value.indexOf(")");
						var n_length = n_end - a_length.index;
						var s_number = value.substr(a_length.index, n_length);

						s_number = s_number.replace(",", ".");

						s_type = s_type.toLowerCase();

						switch (s_type) {
							case "char":
							case "varchar":
								Ext.apply(o_apply, {
									maxLength: Ext.Number.parseInt(s_number),
								});
								break;
							case "dec":
							case "decimal":
							case "int":
							case "integer":
							case "smallint":
							case "bigint":
							case "int":
							case "integer":

								var n_digital;
								var s_first;

								if (s_number.indexOf(".") > -1) {

									var a_split = s_number.split(".");

									var s_digital = a_split[0];
									var s_decimal = a_split[1];

									n_digital =  Ext.Number.parseFloat(s_digital);
									var n_decimal = Ext.Number.parseFloat(s_decimal) || 0;
									var n_precision = n_decimal;


									s_first = "";
									var s_last = "";

									while(n_digital) {
										s_first += "9";
										n_digital--;
									}

									while(n_decimal) {
										s_last += "9";
										n_decimal--;
									}

									var n_maxValue = Ext.Number.parseFloat([s_first, s_last].join("."));

									Ext.apply(o_apply, {
										maxValue: n_maxValue,
										decimalPrecision: n_precision
									});

								}
								else {

									n_digital = Ext.Number.parseFloat(s_number) || 0;
									s_first = "";

									while(n_digital) {
										s_first += "9";
										n_digital--;
									}

									Ext.apply(o_apply, {
										maxValue: Ext.Number.parseInt(s_first),
										decimalPrecision: 0
									});
								}
								break;
							case "timestamp":
							case "isotimestamp":
							case "date":
								Ext.apply(o_apply, {
									maxValue: Ext.Number.parseInt(s_number),
								});

								break;
							default:
								break;
						}

					}

					delete o_config[s_key];

					break;

				default:
					break;
			}
		});

		Ext.apply(o_config, o_apply);

		return o_config;
	},

	createUI: function(o_data, a_definition) {

		var i_self = this;

		var o_processed = i_self.processData(o_data, a_definition);

		var a_items = i_self.createItems(o_processed);

		return a_items;

	},

	createItems: function(o_processed) {

		var i_self = this;

		var a_items = [];

		Ext.Object.each(o_processed, function(s_key, o_property) {

			if (o_property.type == "collection" || o_property.type == "group") {
				if (o_property.apperence == "field") {
					a_items.push(i_self.createField(o_property));
				}
				else {
					a_items.push(i_self.createGroup(o_property));
				}
			}
			else if (o_property.type == "property") {
				a_items.push(i_self.createField(o_property));
			}
		});

		return a_items;
	},

	createFormCollection: function(o_data, a_definition, b_config) {

		var i_self = this;

		var o_formCollection = Ext.Array.findBy(a_definition, function (o_definition) {
			return (o_definition.id == o_data.fcid  ||
				o_definition.name == o_data.fcid) && o_definition.type == "formCollection";
		});

		var o_clone = Ext.clone(o_formCollection);

		var o_rule = o_clone.rule || {};

		Ext.apply(o_clone, o_rule);

		delete o_clone.rule;

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

		if (a_extend.length > 0) {

			var a_recursion = i_self.getExtendedFormCollection(a_extend, a_definition);

			a_recursion.reverse();

			var o_merged = {};

			Ext.Array.each(a_recursion, function(o_extended){

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

					if (Ext.isPrimitive(value)) {
						o_merged[s_key] = value;
					}
					else {
						if (Ext.isArray(value)) {

							var a_temp = Ext.Array.from(o_merged[s_key]) || [];
							var a_value = Ext.Array.from(value);

							a_temp = Ext.Array.merge(a_temp, a_value);

							o_merged[s_key] = a_temp;
						}
						else{
							if (Ext.isObject(value)) {
								o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
							}
						}
					}

				});
			});

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

				if (Ext.isPrimitive(value)) {
					o_merged[s_key] = value;
				}
				else {
					if (Ext.isArray(value)) {

						var a_temp = Ext.Array.from(value) || [];
						var a_value = Ext.Array.from(o_merged[s_key]);

						a_temp = Ext.Array.merge(a_temp, a_value);

						o_merged[s_key] = a_temp;
					}
					else {
						if (Ext.isObject(value)) {
							o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
						}
					}
				}

			});

			o_clone = o_merged;

			delete o_clone.extend;
		}

		var a_fields = Ext.Array.from(o_clone.fields || o_clone.items);

		var o_temp = {};

		Ext.Array.each(a_fields, function(s_field) {
			o_temp[s_field] = o_data[s_field] || "";
		});

		var o_processed = i_self.processData(o_temp, a_definition);

		return b_config ? o_processed : i_self.createItems(o_processed);

	},

	createGroup: function (o_property) {

		var i_self = this;

		var a_items = [];

		Ext.Array.each(o_property.items, function(o_item) {

			var i_field = i_self.createField(o_item);

			i_field.isFormField = false;

			a_items.push(i_field);
		});

		var i_define = Ext.define(null, {

			extend: "Ext.form.FieldSet",

			mixins: {
				field: "Ext.form.field.Field"
			},

			initComponent: function () {

				var i_field = this;

				i_field.initField();

				i_field.callParent(arguments);

				var a_items = i_field.items.getRange();

				Ext.Array.each(a_items, function(i_subfield) {
					i_subfield.on({
						change: {
							fn: function(i_subfield) {
								i_field.checkChange();
							}
						}
					});
				});
			},

			getValue: function () {

				var i_field = this;

				var o_value = {};

				if (!i_field.items.getRange) {
					return i_field.mixins.field.getValue.call(i_field);
				}

				var a_items = i_field.items.getRange();

				Ext.Array.each(a_items, function (i_subfield) {
					o_value[i_subfield.name] = i_subfield.getSubmitValue ? i_subfield.getSubmitValue() : i_subfield.getValue();
				});

				return o_value;
			},

			getSubmitData: function () {
				var i_field = this;
				var o_data = null;

				if (!i_field.disabled && i_field.submitValue) {
					o_data = {};
					o_data[i_field.getName()] = i_field.getSubmitValue();
				}
				return o_data;
			},

			getSubmitValue: function () {

				var i_field = this;

				return i_field.getValue();
			},
			setValue: function (o_value) {

				var i_field = this;

				var a_items = Ext.Array.from(i_field.items.getRange());

				Ext.Array.each(a_items, function (i_subfield) {
					i_subfield.setValue(o_value[i_subfield.name]);
				});

				i_field.mixins.field.setValue.call(i_field, o_value);
			},
			checkChange: function () {

				var i_self = this;
				var newVal;
				var oldVal;

				if (!i_self.suspendCheckChange && !i_self.destroying && !i_self.destroyed) {
					newVal = i_self.getValue();
					oldVal = i_self.lastValue;
					if (i_self.didValueChange(newVal, oldVal)) {
						i_self.lastValue = newVal;
						i_self.fireEvent("change", i_self, newVal, oldVal);
						i_self.onChange(newVal, oldVal);
					}
				}
			},
			didValueChange: function (newVal, oldVal) {

				var s_new = Ext.encode(newVal);
				var s_old = Ext.encode(oldVal);

				return s_new != s_old;
			},
			isDirty: function () {

				var i_field = this;

				var s_originalValue = Ext.encode(i_field.originalValue);
				var s_value = Ext.encode(i_field.getSubmitValue());

				return s_originalValue != s_value;
			}
		});

		if (!o_property.hasOwnProperty("active")) {
			o_property.active = true;
		}

		var i_group = i_define.create({
			title: o_property.title || o_property.label || o_property.name,
			name: o_property.name,
			items: a_items,
			cls: o_property.active ? "" : "pd-form-field-deactive",
			collapsible: true,
			collapsed: false,
			layout: "anchor",
			defaults: {
				labelWidth: 180
			}
		});

		return i_group;
	},

	createField: function (o_property) {

		var i_self = this;
		var o_clone = Ext.clone(o_property);

		if (!o_clone.hasOwnProperty("active")) {
			o_clone.active = true;
		}

		var i_field;

		if (o_clone.type == "collection" || o_clone.type == "group") {

			var a_items = [];

			var a_label = [];

			if (o_clone.hasOwnProperty("prioritized") && !Ext.isEmpty(o_clone.prioritized, true)) {
				var i_prioritized = i_self.createPrioritiezed(o_clone.prioritized);
				a_items.push(i_prioritized);
			}

			a_label.push(o_clone.fieldLabel || o_clone.label || o_clone.name);

			Ext.Array.each(o_clone.items, function (o_item) {

				var i_field = i_self.createField(o_item);

				i_field.fieldLabel = "";
				i_field.isFormField = false;

				a_items.push(i_field);
			});

			var i_define = Ext.define(null, {

				extend: "Ext.form.FieldContainer",
				mixins: {
					field: "Ext.form.field.Field"
				},

				initComponent: function() {

					var i_field = this;

					i_field.initField();

					i_field.callParent(arguments);

					var a_items = i_field.items.getRange();

					Ext.Array.each(a_items, function(i_subfield) {
						i_subfield.on({
							change: {
								fn: function(i_subfield) {
									i_field.checkChange();
								}
							}
						});
					});
				},

				getValue: function () {

					var i_field = this;

					var o_value = {};

					if (!i_field.items.getRange) {
						return i_field.mixins.field.getValue.call(i_field);
					}

					var a_items = i_field.items.getRange();

					Ext.Array.each(a_items, function (i_subfield) {
						o_value[i_subfield.name] = i_subfield.getSubmitValue ? i_subfield.getSubmitValue() : i_subfield.getValue();
					});

					return o_value;
				},

				getSubmitData: function () {
					var i_field = this;
					var o_data = null;

					if (!i_field.disabled && i_field.submitValue) {
						o_data = {};
						o_data[i_field.getName()] = i_field.getSubmitValue();
					}
					return o_data;
				},

				getSubmitValue: function () {

					var i_field = this;

					return i_field.getValue();
				},
				setValue: function (o_value) {

					var i_field = this;

					var a_items = Ext.Array.from(i_field.items.getRange());

					Ext.Array.each(a_items, function (i_subfield) {
						i_subfield.setValue(o_value[i_subfield.name]);
					});

					i_field.mixins.field.setValue.call(i_field, o_value);
				},
				checkChange: function () {

					var i_self = this;
					var newVal;
					var oldVal;

					if (!i_self.suspendCheckChange && !i_self.destroying && !i_self.destroyed) {
						newVal = i_self.getValue();
						oldVal = i_self.lastValue;
						if (i_self.didValueChange(newVal, oldVal)) {
							i_self.lastValue = newVal;
							i_self.fireEvent("change", i_self, newVal, oldVal);
							i_self.onChange(newVal, oldVal);
						}
					}
				},
				didValueChange: function(newVal, oldVal) {

					var s_new = Ext.encode(newVal);
					var s_old = Ext.encode(oldVal);

					return s_new != s_old;
				},
				isDirty: function () {

					var i_field = this;

					var s_originalValue = Ext.encode(i_field.originalValue);
					var s_value = Ext.encode(i_field.getSubmitValue());

					return s_originalValue != s_value;
				}
			});


			i_field = i_define.create({
				title: o_clone.name,
				name: o_clone.name,
				fieldLabel: a_label.join(" / "),
				cls: o_clone.active ? "" : "pd-form-field-deactive",
				items: a_items,
				layout: {
					type: "hbox"
				},
				defaults: {
					margin: "0 10 0 0"
				}
			});
		}
		else {

			var value = o_clone.value;
			var uomValue = "";

			if (Ext.isObject(value)) {
				if (value.hasOwnProperty("prioritized")) {
					o_clone.prioritized = value.prioritized;
				}
				if (value.hasOwnProperty("uom")) {
					uomValue = value.uom;
				}
			}

			var s_datatype = o_clone.datatype;

			o_clone.fieldLabel = o_clone.fieldLabel || o_clone.label || o_clone.name;

			var a_type = /\(\d*|[,.]*d\)/g.exec(s_datatype);

			if (a_type) {
				s_datatype = s_datatype.substr(0, a_type.index);
			}

			s_datatype = s_datatype ? s_datatype.toLowerCase() : "varchar";

			var s_xtype = "textfield";

			switch (s_datatype) {
				case "char":
				case "varchar":

					if (o_clone.hasOwnProperty("values") && !Ext.isEmpty(o_clone.values)) {

						var a_values = Ext.Array.from(o_clone.values);

						var a_result = [];

						Ext.Array.each(a_values, function(value) {

							if (Ext.isString(value)) {
								a_result.push({
									text: value,
									key: value
								});
							}
							else if(Ext.isObject(value)) {

								var o_value = {
									text: value.text || value.key,
									key: value.value || value.key
								};

								a_result.push(o_value);
							}
						});


						var i_store = Ext.create("Ext.data.Store", {
							data: a_result,
							fields: [
								{
									name: "text",
									type: "auto"
								},
								{
									name: "key",
									type: "auto"
								}
							],
							autoLoad: true
						});

						s_xtype = "combobox";

						Ext.apply(o_clone, {
							store: i_store,
							displayField: "text",
							valueField: "key"
						}, o_clone);
					}
					else {
						s_xtype = "textfield";
					}
					break;
				case "dec":
				case "decimal":
				case "int":
				case "integer":
				case "bigint":
				case "int":
				case "integer":

						if (o_clone.hasOwnProperty("values") && !Ext.isEmpty(o_clone.values)) {

							var a_data = Ext.Array.from(o_clone.values);

							var a_result = [];

							Ext.Array.each(a_data, function(value) {

								if (Ext.isString(value)) {
									a_result.push({
										text: value,
										key: value
									});
								}
								else if(Ext.isObject(value)) {

									var o_value = {
										text: value.text || value.key,
										key: value.value || value.key
									};

									a_result.push(o_value);
								}
							});

							var i_pStore = Ext.create("Ext.data.Store", {
								data: a_result,
								fields: [
									{
										name: "text",
										type: "auto"
									},
									{
										name: "key",
										type: "integer"
									}
								],
								autoLoad: true
							});

							s_xtype = "combobox";

							Ext.apply(o_clone, {
								store: i_pStore,
								displayField: "text",
								valueField: "key"
							});
						}
						else {
							s_xtype = "numberfield";
						}


					break;
				case "smallint":
					if (o_clone.hasOwnProperty("values") && !Ext.isEmpty(o_clone.values)) {

						var i_sStore = Ext.create("Ext.data.Store", {
							data: Ext.Array.from(o_clone.values),
							fields: [
								{
									name: "key",
									type: "auto"
								},
								{
									name: "value",
									type: "integer"
								}
							],
							autoLoad: true
						});

						s_xtype = "combobox";

						Ext.apply(o_clone, {
							store: i_sStore,
							displayField: "key",
							valueField: "value"
						});
					}
					else {

						s_xtype = "checkbox";

						Ext.apply(o_clone, {
							inputValue: 1,
							uncheckedValue: 0
						});
					}
					break;
				case "timestamp":
				case "isotimestamp":
						s_xtype = "isotimestampfield";
					break;
				case "date":
						s_xtype = "datefield";
					break;
				default:
					break;
			}

			if (o_clone.apperence) {

				switch(o_clone.apperence) {
					case "date":
						o_clone.apperence = "isotimestampfield";
						o_clone.datatype = "timestamp";
						s_xtype = "isotimestampfield";
						break;
				}
			}

			if(o_clone.hasOwnProperty("uom") && Ext.isEmpty(o_clone.uom)) {
				delete o_clone.uom;
			}

			if(o_clone.hasOwnProperty("prioritized") && Ext.isEmpty(o_clone.prioritized)) {
				delete o_clone.prioritized;
			}

			if (o_clone.hasOwnProperty("uom") || o_clone.hasOwnProperty("prioritized")) {

				var s_label = ip2.i18n(o_clone.fieldLabel);
				o_clone.fieldLabel = "";
				o_clone.originalValue = o_clone.value = value.value;

				var i_uomfield = Ext.define(null, {

					extend: "Ext.form.FieldContainer",
					mixins: {
						field: "Ext.form.field.Field"
					},

					initComponent: function() {

						var i_field = this;

						i_field.initField();

						i_field.callParent(arguments);

						var a_items = i_field.items.getRange();

						Ext.Array.each(a_items, function(i_subfield) {
							i_subfield.on({
								change: {
									fn: function(i_subfield) {
										i_field.checkChange();
									}
								}
							});
						});
					},

					getValue: function () {

						var i_field = this;

						var o_value = {};

						if (!i_field.items.getRange) {
							return i_field.mixins.field.getValue.call(i_field);
						}

						var a_items = i_field.items.getRange();

						Ext.Array.each(a_items, function (i_subfield) {
							if (i_subfield.uom) {
								o_value.value = i_subfield.getSubmitValue ? i_subfield.getSubmitValue() : i_subfield.getValue();
							}
							else {
								o_value[i_subfield.name] = i_subfield.getSubmitValue ? i_subfield.getSubmitValue() : i_subfield.getValue();
							}
						});

						return o_value;
					},

					getSubmitData: function () {
						var i_field = this;
						var o_data = null;

						if (!i_field.disabled && i_field.submitValue) {
							o_data = {};
							o_data[i_field.getName()] = i_field.getSubmitValue();
						}
						return o_data;
					},

					getSubmitValue: function () {

						var i_field = this;

						return i_field.getValue();
					},
					setValue: function (o_value) {

						var i_field = this;

						var a_items = Ext.Array.from(i_field.items.getRange());

						Ext.Array.each(a_items, function (i_subfield) {
							i_subfield.setValue(o_value[i_subfield.name]);
						});

						i_field.mixins.field.setValue.call(i_field, o_value);
					},
					checkChange: function () {

						var i_self = this;
						var newVal;
						var oldVal;

						if (!i_self.suspendCheckChange && !i_self.destroying && !i_self.destroyed) {
							newVal = i_self.getValue();
							oldVal = i_self.lastValue;
							if (i_self.didValueChange(newVal, oldVal)) {
								i_self.lastValue = newVal;
								i_self.fireEvent("change", i_self, newVal, oldVal);
								i_self.onChange(newVal, oldVal);
							}
						}
					},
					didValueChange: function(newVal, oldVal) {

						var s_new = Ext.encode(newVal);
						var s_old = Ext.encode(oldVal);

						return s_new != s_old;
					},
					isDirty: function () {

						var i_field = this;

						var s_originalValue = Ext.encode(i_field.originalValue);
						var s_value = Ext.encode(i_field.getSubmitValue());

						return s_originalValue != s_value;
					}
				});

				var i_primary = Ext.widget(s_xtype, o_clone);


				var i_uom;
				var i_prioritized;

				var a_temp = [
					i_primary
				];

				if (o_clone.hasOwnProperty("uom") && !Ext.isEmpty(o_clone.uom)) {
					i_uom = i_self.createUOM(o_clone.uom, uomValue);

					a_temp.push(i_uom);
				}

				if (o_clone.hasOwnProperty("prioritized") && !Ext.isEmpty(o_clone.prioritized, true)) {

					i_prioritized = i_self.createPrioritiezed(o_clone.prioritized);

					a_temp.unshift(i_prioritized);
				}

				i_field = i_uomfield.create({
					name: o_clone.name,
					fieldLabel: s_label,
					cls: o_clone.active ? "" : "pd-form-field-deactive",
					layout: {
						type: "hbox"
					},
					items: a_temp,
					defaults: {
						margin: "0 10 0 0"
					}
				});

			}
			else{

				Ext.apply(o_clone, {
					cls: o_clone.active ? "" : "pd-form-field-deactive",
				});

				i_field = Ext.widget(s_xtype, o_clone);
			}
		}

		i_field.resetOriginalValue();

		return i_field;
	},

	createUOM: function(value, propValue) {

		var o_config = {
			name: "uom",
			isFormField: false,
			margin: "0 0 0 0"
		};

		var s_xtype = "";

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

		var a_data = [];

		Ext.Array.each(a_values, function(value) {

			if (Ext.isString(value)) {
				a_data.push({
					text: value,
					key: value,
					active: true
				});
			}
			else if(Ext.isObject(value)) {

				var o_value = {
					text: value.text || value.key,
					key: value.value || value.key,
					active: value.active
				};

				a_data.push(o_value);
			}
		});

		var i_store = Ext.create("Ext.data.Store", {
			data: a_data,
			fields: [
				{
					name: "text",
					type: "auto"
				},
				{
					name: "key",
					type: "auto"
				},
				{
					name: "active",
					type: "auto",
					defaultValue: true
				}
			],
			idProperty: "key",
			autoLoad: true
		});

		s_xtype = "combobox";

		var i_listTpl = Ext.create("Ext.XTemplate",
			"<ul class=\"x-list-plain\">",
				"<tpl for=\".\">",
					"<tpl if=\"this.isActive(values.active)\">",
						"<li role=\"option\" class=\"x-boundlist-item\">{text}</li>",
					"<tpl else>",
						"<li role=\"option\" class=\"x-boundlist-item\"><span style=\"opacity:0.5;\">{text}<span></li>",
					"</tpl>",
				"</tpl>",
			"</ul>",
			{
				isActive: function(value) {
					return value;
				}
			}
		);

		Ext.apply(o_config, {
			store: i_store,
			displayField: "text",
			valueField: "key",
			value: propValue,
			multiSelect: false,
			tpl: i_listTpl,
			listeners: {
				change: {
					fn: function(i_field, value) {

						var i_selected = i_field.getSelectedRecord();
						var i_inputEl;
						var b_active = i_field.hasOwnProperty("active") ? i_field.active : true;

						if (i_selected) {
							b_active = i_selected.get("active");

							i_inputEl = i_field.inputEl;

							if (i_inputEl) {
								i_inputEl.setStyle("opacity", b_active ? "1" : "0.5");
							}
						}
						else {

							i_inputEl = i_field.inputEl;

							if (i_inputEl) {
								i_inputEl.setStyle("opacity", b_active ? "1" : "0.5");
							}
						}

					}
				}
			}
		});

		var i_field = Ext.widget(s_xtype, o_config);

		return i_field;
	},

	createPrioritiezed: function(value) {

		var o_config = {
			name: "prioritized",
			isFormField: false,
			value: value,
			inputValue: true,
			uncheckedValue: false
		};

		var i_field = Ext.widget("checkbox", o_config);

		return i_field;
	},

	getFormFields: function(o_formCollection, a_definition) {

		var i_self = this;

		var o_clone = Ext.clone(o_formCollection);

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

		if (a_extend.length > 0) {

			var a_recursion = i_self.getExtendedFormCollection(a_extend, a_definition);

			a_recursion.reverse();

			var o_merged = {};

			Ext.Array.each(a_recursion, function(o_extended){

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

					if (Ext.isPrimitive(value)) {
						o_merged[s_key] = value;
					}
					else {
						if (Ext.isArray(value)) {

							var a_temp = Ext.Array.from(o_merged[s_key]) || [];
							var a_value = Ext.Array.from(value);

							a_temp = Ext.Array.merge(a_temp, a_value);

							o_merged[s_key] = a_temp;
						}
						else{
							if (Ext.isObject(value)) {
								o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
							}
						}
					}

				});
			});

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

				if (Ext.isPrimitive(value)) {
					o_merged[s_key] = value;
				}
				else {
					if (Ext.isArray(value)) {

						var a_temp = Ext.Array.from(value) || [];
						var a_value = Ext.Array.from(o_merged[s_key]);

						a_temp = Ext.Array.merge(a_temp, a_value);

						o_merged[s_key] = a_temp;
					}
					else {
						if (Ext.isObject(value)) {
							o_merged[s_key] = Ext.apply(o_merged[s_key] || {}, value);
						}
					}
				}

			});

			o_clone = o_merged;

			delete o_clone.extend;
		}

		var a_fields = Ext.Array.from(o_clone.fields || o_clone.items);

		return a_fields;
	},

	checkPropertyUsages: function(s_value, f_callback) {

		f_callback = f_callback || Ext.emptyFn;

		Ext.Ajax.request({
			url: [
				"/portfolio/pd/whereDoPropertyGetUsed",
				s_value
			].join("/"),
			success: function(i_response) {

				var o_result = Ext.decode(i_response.responseText, true) || {};

				f_callback(o_result, true);
			},
			failure: function(o_err) {
				f_callback(o_err, false);
			}
		});
	},

	checkCollectionUsages: function(s_value, f_callback) {

		f_callback = f_callback || Ext.emptyFn;

		Ext.Ajax.request({
			url: [
				"/portfolio/pd/whereDoCollectionGetUsed",
				s_value
			].join("/"),
			success: function(i_response) {

				var o_result = Ext.decode(i_response.responseText, true) || {};

				f_callback(o_result, true);
			},
			failure: function(o_err) {
				f_callback(o_err, false);
			}
		});
	}
});
