/**
 * Hierarchical mixin for {@link Terrasoft.Grid}.
 */
Ext.define("Terrasoft.controls.mixins.HierarchicalGridMixin", {
	alternateClassName: "Terrasoft.HierarchicalGridMixin",

	/**
  * Index of hierarchical display of data in the list.
  * @cfg {Boolean} [hierarchical="false"]
  */
	hierarchical: false,

	/**
  * @type {Array}
  */
	expandHierarchyLevels: null,

	/**
  * The template element used to label the minimized state of the hierarchy node.
  * @protected
  * @type {Ext.Template}
  */
	// jscs:disable
	/*jshint quotmark: false */
	hierarchicalPlus: new Ext.Template('<div id="{id}" class="{cls}"></div>'),
	/*jshint quotmark: true */
	// jscs:enable

	/**
  * The template element used to mark the expanded state of the hierarchy node.
  * @protected
  * @type {Ext.Template}
  */
	// jscs:disable
	/*jshint quotmark: false */
	hierarchicalMinus: new Ext.Template('<div id="{id}" class="{cls}"></div>'),
	/*jshint quotmark: true */
	// jscs:enable

	/**
  * CSS  switch class of expandingcollapsing the hierarchy branch to the 'collapsed' state.
  * @protected
  * @property {String} hierarchicalPlusCss
  */
	hierarchicalPlusCss: "grid-toggle-plus",

	/**
  *  CSS  switch class of expandingcollapsing the hierarchy branch to the 'expand' state.
  * @protected
  * @property {String} hierarchicalMinusCss
  */
	hierarchicalMinusCss: "grid-toggle-minus",

	/**
  *  CSS  switch class of expandingcollapsing the hierarchy branch to the state
  * in which there is no need to display the switch.
  * @property {String} hierarchicalEmptyCss
  */
	hierarchicalEmptyCss: "grid-toggle-empty",

	/**
  * The prefix of the DOM element identifier responsible for expanding/collapsing the hierarchy branch.
  * @protected
  * @property {String} hierarchicalTogglePrefix
  */
	hierarchicalTogglePrefix: "-toggle-",

	/**
  * The prefix of the DOM element class of the responder to display and hide the subordinate branches in the hierarchy.
  * @protected
  * @property {String} hierarchicalChildrenPrefix
  */
	hierarchicalChildrenPrefix: "-children-",

	/**
  * A value key in the data that serves as a pointer to the parent's identifier when building the data hierarchy.
  * @type {String}
  */
	hierarchicalColumnName: "Parent",

	/**
  * Points to the need for using level rendering.
  * @type {Boolean} [useLevelRendering="false"]
  */
	useLevelRendering: false,

	/**
  * A set of elements that track client events by expanding/collapsing hierarchy branches.
  * @protected
  * @type {Ext.CompositeElement}
  */
	toggleRows: null,

	/**
  * ndent the line in the list.
  * @type {Number}
  */
	baseOffset: 32,

	/**
  * The indent of the expand/collapse button of the branch.
  * @type {Number}
  */
	contentOffset: 32,

	/**
  * Indentation of the checkbox in the mode of multiple selection (width + margin-right).
  * @type {Number}
  */
	checkboxOffset: 32,

	/**
  * Returns margin-right or margin-left style with offset, depending on RTL or LTR mode.
  * @private
  * @param {Object} offsetOptions Options for calculating margin offset.
  * @return {String} Margin style with calculated offset.
  */
	_getMarginOffset: function (offsetOptions) {
		var marginLeftOffset = this.contentOffset * offsetOptions.level + offsetOptions.marginLeftOffset;
		var direction = Terrasoft.getIsRtlMode() ? "right" : "left";
		return Ext.String.format("margin-{0}: {1}px", direction, marginLeftOffset);
	},

	/**
  * Returns padding-right or padding-left style, depending on RTL or LTR mode.
  * @private
  * @param {Object} offsetOptions Options for calculating padding offset.
  * @return {String} Padding style with calculated offset.
  */
	_getPaddingOffset: function (offsetOptions) {
		var paddingLeftOffset = this.contentOffset * offsetOptions.level + offsetOptions.paddingLeftOffset;
		var direction = Terrasoft.getIsRtlMode() ? "right" : "left";
		var paddingOffset = Ext.String.format("padding-{0}:  {1}px", direction, paddingLeftOffset);
		return paddingOffset;
	},

	/**
  * Filters grid rows by parent unique identifier.
  * @private
  * @param {String} parentId Parent unique identifier.
  * @return {Array} Filtered rows.
  */
	filterRowsByParent: function (parentId) {
		var hierarchicalColumnName = this.hierarchicalColumnName;
		return this.rows.filter(function (item) {
			return item.hasOwnProperty(hierarchicalColumnName) && item[hierarchicalColumnName] === parentId;
		}, this);
	},

	/**
  * Adds the hierarchicalColumnName and rowLevel properties to the options for the hierarchical list.
  * @param {BaseViewModel} item A collection item.
  * @param {Object} options An object that contains an array of strings and additional parameters.
  */
	addHierarchicalOptions: function (item, options) {
		var firstParentItem = item.get(this.hierarchicalColumnName);
		options[this.hierarchicalColumnName] = firstParentItem;
		if (this.type === "listed" && firstParentItem) {
			var firstParentItemDom = this.getDomRow(firstParentItem);
			var parentLevel = parseInt(firstParentItemDom.getAttribute("level"), 10);
			options.rowLevel = parentLevel + 1;
		}
	},

	/**
  * Removes the hierarchicalTogglePrefix from the string and, if the list is hierarchical, 
  * deletes the hierarchicalTogglePrefix from the parent, if it no longer has child elements.
  * @private
  * @param {Terrasoft.BaseViewModel} item A collection item.
  */
	deleteItemHierarchicalToggle: function (item) {
		var wrapEl = this.getWrapEl();
		var toggles = wrapEl.select("[id*=\"" + this.hierarchicalTogglePrefix + "\"]");
		var id = item.get(this.primaryColumnName);
		var toggleId = this.id + this.hierarchicalTogglePrefix + id;
		toggles.each(function (item) {
			if (toggleId === item.dom.id) {
				Ext.removeNode(item.dom);
				return false;
			}
		}, this);
		if (this.hierarchical) {
			var parentRowId = item.get(this.hierarchicalColumnName);
			var parentRow = this.collection.find(parentRowId);
			var children = [];
			this.getAllItemChildren(children, parentRowId);
			if (Ext.isEmpty(parentRowId) || Ext.isEmpty(parentRow) || children.length > 0) {
				return;
			}
			this.removeExpandHierarchyLevel(parentRowId);
			this.deleteItemHierarchicalToggle(parentRow);
		}
	},

	/**
  * Handles hierarchy plus click.
  * @param {String} rowId Row identifier.
  */
	toggleHierarchyFolding: function (rowId) {
		var root = this.getWrapEl();
		var toggle = Ext.get(this.id + this.hierarchicalTogglePrefix + rowId);
		var children = Ext.select("[class~=\"" + this.id + this.hierarchicalChildrenPrefix + rowId + "\"]", root);
		var status;
		if (toggle.hasCls(this.hierarchicalPlusCss)) {
			this.expandHierarchy(toggle, children, rowId);
			this.addExpandHierarchyLevel(rowId);
			status = true;
		} else if (toggle.hasCls(this.hierarchicalMinusCss)) {
			this.collapseHierarchy(toggle, children);
			this.removeExpandHierarchyLevel(rowId);
			status = false;
		}
		this.fireEvent("updateExpandHierarchyLevels", rowId, status);
	},

	/**
  * Expands level of hierarchy.
  * @param {Object} toggle Toggle element.
  * @param {Array} children Hierarchy level elements.
  * @param {String} rowId Row identifier.
  */
	expandHierarchy: function (toggle, children, rowId) {
		toggle.removeCls(this.hierarchicalPlusCss);
		toggle.addCls(this.hierarchicalMinusCss);
		if (Ext.isEmpty(children)) {
			return;
		}
		if (rowId && Ext.isEmpty(children.elements) && this.useLevelRendering) {
			var rowItem = this.getDomRow(rowId);
			var childItems = [];
			var options = {};
			var rowLevelAtt = rowItem.getAttribute("level") || 0;
			options.rowLevel = parseInt(rowLevelAtt) + 1;
			options.levelRows = this.filterRowsByParent(rowId);
			this.renderHierarchicalListedLevel(childItems, options);
			Ext.DomHelper.insertAfter(rowItem, Ext.DomHelper.markup([childItems]));
		}
		children.each(function (row) {
			row.removeCls(this.hiddenCss);
		}, this);
	},

	collapseHierarchy: function (toggle, children) {
		toggle.removeCls(this.hierarchicalMinusCss);
		toggle.addCls(this.hierarchicalPlusCss);
		children.each(function (row) {
			if (this.type === "listed") {
				var childToggleRows = Ext.dom.Query.selectNode("[class~=\"" + this.hierarchicalMinusCss + "\"]", row.dom);
				if (childToggleRows) {
					childToggleRows.click();
				}
			}
			row.addCls(this.hiddenCss);
		}, this);
	},

	addExpandHierarchyLevel: function (rowId) {
		var expandHierarchyLevels = Ext.Array.clone(this.expandHierarchyLevels);
		var id = rowId.toString();
		if (!Terrasoft.contains(expandHierarchyLevels, id)) {
			expandHierarchyLevels.push(id);
		}
		this.expandHierarchyLevels = expandHierarchyLevels;
	},

	removeExpandHierarchyLevel: function (rowId) {
		var expandHierarchyLevels = Ext.Array.clone(this.expandHierarchyLevels);
		var id = rowId.toString();
		if (Terrasoft.contains(expandHierarchyLevels, id)) {
			expandHierarchyLevels = Terrasoft.without(expandHierarchyLevels, id);
		}
		this.expandHierarchyLevels = expandHierarchyLevels;
	},

	setExpandHierarchyLevel: function (values) {
		for (var i in values) {
			this.addExpandHierarchyLevel(values[i]);
		}
	},

	/**
  * A method for creating a nested layout for a hierarchical method of displaying a modular grid.
  * @protected
  * @param {Array} result
  * @param {Object} options
  * @return {Number} The number of children that were added for the iteration.
  */
	renderTiledHierarchicalGrid: function (result, options) {
		var rows = options.rows || this.rows;
		var startResultLength = result.length;
		var parent = options[this.hierarchicalColumnName];
		var multiSelect = this.multiSelect;
		for (var index = 0, length = rows.length; index < length; index += 1) {
			var row = rows[index];
			var rowHasNesting = row[this.hasNestingColumnName];
			options.row = row;
			options[this.hierarchicalColumnName] = row[this.primaryColumnName];
			var id = (row[this.primaryColumnName] || index).toString();
			var rowStyles = this.rowsStyles[id];
			var subRows;
			var toggleCss;
			var checkbox;
			var htmlConfig = this.getDefaultRowHtmlConfig(row);
			if (!row.hasOwnProperty(this.hierarchicalColumnName) && !parent) {
				Ext.apply(htmlConfig, {
					tag: "div",
					cls: "grid-row grid-pad " + this.theoreticallyActiveRowCss,
					style: Ext.DomHelper.generateStyles(rowStyles),
					id: this.id + this.collectionItemPrefix + id,
					children: [{
						tag: "div",
						cls: multiSelect ? "grid-fixed-col-2" : "grid-fixed-col",
						html: ""
					}]
				});
				this.renderColumns(htmlConfig.children, options);
				subRows = this.renderTiledHierarchicalGrid(htmlConfig.children, options);
				toggleCss = this.hierarchicalEmptyCss;
				if (subRows > 0 || rowHasNesting) {
					toggleCss = this.hierarchicalPlusCss;
				}
				if (Terrasoft.contains(this.expandHierarchyLevels, id.toString())) {
					toggleCss = this.hierarchicalMinusCss;
				}
				htmlConfig.children[0].html = this.hierarchicalPlus.apply({
					id: this.id + this.hierarchicalTogglePrefix + row[this.primaryColumnName],
					cls: toggleCss + " grid-listed-row-control"
				});
				if (multiSelect) {
					checkbox = this.createCheckbox({
						classes: {
							wrapClass: ["grid-listed-row-control"]
						},
						value: id
					});
					if (Terrasoft.contains(this.selectedRows, id)) {
						htmlConfig.cls += " " + this.selectedRowCss;
						checkbox.setChecked(true);
					}
					htmlConfig.children[0].html += checkbox.generateHtml();
					this.checkboxes.push(checkbox);
				} else {
					if (this.activeRow === id) {
						htmlConfig.cls += " " + this.activeRowCss;
					}
				}
				result.push(htmlConfig);
			} else if (row[this.hierarchicalColumnName] === parent) {
				var childrenClass = this.id + this.hierarchicalChildrenPrefix + row[this.hierarchicalColumnName];
				Ext.apply(htmlConfig, {
					tag: "div",
					cls: "grid-row " + childrenClass,
					children: [{
						tag: "div",
						cls: "grid-row grid-pad " + this.theoreticallyActiveRowCss,
						style: Ext.DomHelper.generateStyles(rowStyles),
						id: this.id + this.collectionItemPrefix + id,
						children: [{
							tag: "div",
							cls: multiSelect ? "grid-fixed-col-2" : "grid-fixed-col",
							html: ""
						}]
					}]
				});
				if (!Terrasoft.contains(this.expandHierarchyLevels, parent.toString())) {
					htmlConfig.cls += " " + this.hiddenCss;
				}
				this.renderColumns(htmlConfig.children[0].children, options);
				subRows = this.renderTiledHierarchicalGrid(htmlConfig.children[0].children, options);
				toggleCss = this.hierarchicalEmptyCss;
				if (subRows > 0 || rowHasNesting) {
					toggleCss = this.hierarchicalPlusCss;
				}
				if (Terrasoft.contains(this.expandHierarchyLevels, id.toString())) {
					toggleCss = this.hierarchicalMinusCss;
				}
				htmlConfig.children[0].children[0].html = this.hierarchicalPlus.apply({
					id: this.id + this.hierarchicalTogglePrefix + row[this.primaryColumnName],
					cls: toggleCss + " grid-listed-row-control"
				});
				if (multiSelect) {
					checkbox = this.createCheckbox({
						classes: {
							wrapClass: ["grid-listed-row-control"]
						},
						value: id
					});
					if (Terrasoft.contains(this.selectedRows, id)) {
						htmlConfig.children[0].cls += " " + this.selectedRowCss;
						checkbox.setChecked(true);
					}
					htmlConfig.children[0].children[0].html += checkbox.generateHtml();
					this.checkboxes.push(checkbox);
				} else {
					if (this.activeRow === id) {
						htmlConfig.children[0].cls += " " + this.activeRowCss;
					}
				}
				result.push(htmlConfig);
			}
			continue;
		}
		return result.length - startResultLength;
	},

	/**
  * Renders listed hierarchical grid elements.
  * @protected
  * @param {Array} result Elements html configuration inforamtion.
  * @param {Object} options Options for rendering.
  * @return {Number} The number of children, that was added per iteration.
  */
	renderListedHierarchicalGrid: function (result, options) {
		var level = options.rowLevel || 0;
		var rows = options.rows || this.rows;
		var startResultLength = result.length;
		var hierarchicalColumnName = this.hierarchicalColumnName;
		if (this.useLevelRendering && Terrasoft.isEmptyObject(options)) {
			var childItems = this.getHierarchicalListedTopLevelItems();
			this.renderHierarchicalChildItems(result, childItems, level);
			return result.length - startResultLength;
		}
		var parent = options[hierarchicalColumnName];
		for (var index = 0, length = rows.length; index < length; index += 1) {
			var row = rows[index];
			options.row = row;
			options[hierarchicalColumnName] = row[this.primaryColumnName];
			var id = (row[this.primaryColumnName] || index).toString();
			if (!row.hasOwnProperty(hierarchicalColumnName) && !parent || row[hierarchicalColumnName] === parent) {
				var htmlConfig = this.getDefaultRowHtmlConfig(row);
				this.applyHierarchicalRowDefaultOptions(htmlConfig, { id: id, level: level });
				this.renderColumns(htmlConfig.children, options);
				result.push(htmlConfig);
				options.rowLevel = level + 1;
				var subRows = this.renderListedHierarchicalGrid(result, options);
				var rowHasNesting = row[this.hasNestingColumnName];
				htmlConfig.children.unshift({
					tag: "div",
					cls: "grid-fixed-col",
					html: ""
				});
				var baseOffset = this.baseOffset;
				if (this.multiSelect) {
					baseOffset = this.baseOffset + this.checkboxOffset;
					this.processListedHierarchicalMultiSelectGrid(htmlConfig, id);
				}
				if (!this.multiSelect && this.activeRow === id) {
					htmlConfig.cls += " " + this.activeRowCss;
				}
				var isHierarchicalMinusCss = Terrasoft.contains(this.expandHierarchyLevels, id);
				this.addToggleCssToListedHierarchicalGrid(htmlConfig, {
					isHierarchicalPlusCss: subRows > 0 || rowHasNesting,
					isHierarchicalMinusCss: isHierarchicalMinusCss,
					row: row
				});
				this.addOffsetToListedHierarchicalGridRow(htmlConfig, {
					level: level,
					marginLeftOffset: 6,
					paddingLeftOffset: baseOffset
				});
				if (level > 0) {
					var childrenClass = this.id + this.hierarchicalChildrenPrefix + row[this.hierarchicalColumnName];
					htmlConfig.cls += " " + childrenClass;
					if (!Terrasoft.contains(this.expandHierarchyLevels, parent.toString())) {
						htmlConfig.cls += " " + this.hiddenCss;
					}
				}
			}
		}
		return result.length - startResultLength;
	},

	/**
  * Renders child rows for hierarchical grid row.
  * @private
  * @param {Array} result Elements html configuration inforamtion.
  * @param {Array} items Child items.
  * @param {Number} level Child items level.
  */
	renderHierarchicalChildItems: function (result, items, level) {
		var options = {};
		Terrasoft.each(items, function (levelItem) {
			var childItems = this.filterRowsByParent(levelItem.Id);
			options.rowLevel = level;
			options.levelRows = [levelItem];
			var childConfig = [];
			this.renderHierarchicalListedLevel(childConfig, options);
			if (Terrasoft.contains(this.expandHierarchyLevels, levelItem.Id)) {
				this.addToggleCssToListedHierarchicalGrid(childConfig[0], {
					isHierarchicalPlusCss: false,
					isHierarchicalMinusCss: true,
					row: levelItem
				});
				result.push(childConfig);
				this.renderHierarchicalChildItems(result, childItems, level + 1);
			} else {
				result.push(childConfig);
			}
		}, this);
	},

	/**
  * Returns hierarchical top row items.
  * @private
  * @return {Array}
  */
	getHierarchicalListedTopLevelItems: function () {
		var hierarchicalColumnName = this.hierarchicalColumnName;
		var topLevel = this.rows.filter(function (item) {
			return !item.hasOwnProperty(hierarchicalColumnName) && Ext.isEmpty(item[hierarchicalColumnName]);
		});
		return topLevel;
	},

	/**
  * Renders hierarchical level items.
  * @private
  * @param {Array} levelItems Rendered items.
  * @param {Object} options Rendering options.
  */
	renderHierarchicalListedLevel: function (levelItems, options) {
		var levelRows = options.levelRows;
		var level = options.rowLevel || 0;
		var rows = this.rows;
		var hierarchicalColumnName = this.hierarchicalColumnName;
		Terrasoft.each(levelRows, function (row, index) {
			var rowId = row.Id;
			options.row = row;
			options[hierarchicalColumnName] = row[this.primaryColumnName];
			var id = (row[this.primaryColumnName] || index).toString();
			var htmlConfig = this.getDefaultRowHtmlConfig(row);
			this.applyHierarchicalRowDefaultOptions(htmlConfig, { id: id, level: level });
			this.renderColumns(htmlConfig.children, options);
			levelItems.push(htmlConfig);
			htmlConfig.children.unshift({
				tag: "div",
				cls: "grid-fixed-col",
				html: ""
			});
			var baseOffset = this.baseOffset;
			if (this.multiSelect) {
				baseOffset = this.baseOffset + this.checkboxOffset;
				this.processListedHierarchicalMultiSelectGrid(htmlConfig, id);
			}
			if (!this.multiSelect && this.activeRow === id) {
				htmlConfig.cls += " " + this.activeRowCss;
			}
			var nestedElement = {};
			nestedElement[hierarchicalColumnName] = rowId;
			var firstNestingElement = Terrasoft.findWhere(rows, nestedElement);
			var isRowHasNestingElements = row[this.hasNestingColumnName];
			this.addToggleCssToListedHierarchicalGrid(htmlConfig, {
				isHierarchicalPlusCss: !Ext.isEmpty(firstNestingElement) || isRowHasNestingElements,
				isHierarchicalMinusCss: false,
				row: row
			});
			this.addOffsetToListedHierarchicalGridRow(htmlConfig, {
				level: level,
				marginLeftOffset: 6,
				paddingLeftOffset: baseOffset
			});
			if (level > 0) {
				var childrenClass = this.id + this.hierarchicalChildrenPrefix + row[hierarchicalColumnName];
				htmlConfig.cls += " " + childrenClass;
			}
		}, this);
	},

	/**
  * Adds offset to listed hierarchical grid..
  * @private
  * @param {Object} htmlConfig Html configuration information for rendering row.
  * @param {Object} offsetOptions Offset options.
  * @param {Number} offsetOptions.marginLeftOffset Left margin offset.
  * @param {Number} offsetOptions.paddingLeftOffset Left padding offset.
  * @param {Object} offsetOptions.level Hierarchical grid level.
  */
	addOffsetToListedHierarchicalGridRow: function (htmlConfig, offsetOptions) {
		var children = htmlConfig && htmlConfig.children;
		if (children && children.length > 1) {
			var fixedCol = children[0];
			var firstCell = children[1];
			fixedCol.style = this._getMarginOffset(offsetOptions);
			firstCell.style = this._getPaddingOffset(offsetOptions);
		}
	},

	/**
  * Adds toggle styles to listed hierarchical grid..
  * @private
  * @param {Object} htmlConfig Html configuration information for rendering row.
  * @param {Object} options Toggle options.
  * @param {Boolean} options.isHierarchicalPlusCss Says to set hierarchical plus css.
  * @param {Boolean} options.isHierarchicalMinusCss Says to set hierarchical minus css.
  * @param {Object} options.row Listed hierarchical row.
  */
	addToggleCssToListedHierarchicalGrid: function (htmlConfig, options) {
		var children = htmlConfig && htmlConfig.children;
		if (children && children.length > 0) {
			var fixedCol = children[0];
			var toggleCss = this.hierarchicalEmptyCss;
			if (options.isHierarchicalPlusCss) {
				toggleCss = this.hierarchicalPlusCss;
			}
			if (options.isHierarchicalMinusCss) {
				toggleCss = this.hierarchicalMinusCss;
			}
			var togglerId = this.id + this.hierarchicalTogglePrefix + options.row[this.primaryColumnName];
			var togglerHtml = this.hierarchicalPlus.apply({
				id: togglerId,
				cls: Ext.String.format("{0} grid-listed-row-control", toggleCss)
			});
			fixedCol.html = fixedCol.html.indexOf(togglerId) === -1 ? togglerHtml + fixedCol.html : togglerHtml;
		}
	},

	/**
  * Process listed hierarchical multi select grid.
  * @private
  * @param {Object} htmlConfig Html configuration information for rendering row.
  * @param {String} rowId Dom row id.
  */
	processListedHierarchicalMultiSelectGrid: function (htmlConfig, rowId) {
		var children = htmlConfig && htmlConfig.children;
		if (children && children.length > 0) {
			var fixedCol = children[0];
			fixedCol.cls = "grid-fixed-col-2";
			var checkbox = this.createCheckbox({
				classes: {
					wrapClass: ["grid-listed-row-control"]
				},
				value: rowId
			});
			if (Terrasoft.contains(this.selectedRows, rowId)) {
				htmlConfig.cls += " " + this.selectedRowCss;
				checkbox.setChecked(true);
			}
			fixedCol.html = checkbox.generateHtml() + fixedCol.html;
			this.checkboxes.push(checkbox);
		}
	},

	/**
  * Applies hierarchical default options to row.
  * @private
  * @param {Object} htmlConfig Html configuration information for rendering row.
  * @param {Object} rowConfig Row configuration information.
  */
	applyHierarchicalRowDefaultOptions: function (htmlConfig, rowConfig) {
		var id = rowConfig.id;
		var rowStyles = this.rowsStyles[id];
		var rowClass = Ext.String.format("{0} {1}", this.listedRowsCss, this.theoreticallyActiveRowCss);
		var rowDomId = this.id + this.collectionItemPrefix + id;
		Ext.apply(htmlConfig, {
			tag: "div",
			cls: rowClass,
			style: Ext.DomHelper.generateStyles(rowStyles),
			id: rowDomId,
			children: [],
			level: rowConfig.level
		});
	}

});