// Copyright (c) 2015, JINGROW and Contributors
// MIT License. See license.txt

jingrow.provide("jingrow.model");

$.extend(jingrow.model, {
	all_fieldtypes: [
		"Autocomplete",
		"Attach",
		"Attach Image",
		"Barcode",
		"Button",
		"Check",
		"Code",
		"Color",
		"Currency",
		"Data",
		"Date",
		"Datetime",
		"Duration",
		"Dynamic Link",
		"Float",
		"Geolocation",
		"Heading",
		"HTML",
		"HTML Editor",
		"Icon",
		"Image",
		"Int",
		"JSON",
		"Link",
		"Long Text",
		"Markdown Editor",
		"Password",
		"Percent",
		"Phone",
		"Read Only",
		"Rating",
		"Select",
		"Signature",
		"Small Text",
		"Table",
		"Table MultiSelect",
		"Text",
		"Text Editor",
		"Time",
		"Jeditor",
	],

	no_value_type: [
		"Section Break",
		"Column Break",
		"Tab Break",
		"HTML",
		"Table",
		"Table MultiSelect",
		"Button",
		"Image",
		"Fold",
		"Heading",
	],

	layout_fields: ["Section Break", "Column Break", "Tab Break", "Fold"],

	std_fields_list: [
		"name",
		"owner",
		"creation",
		"modified",
		"modified_by",
		"_user_tags",
		"_comments",
		"_assign",
		"_liked_by",
		"pagestatus",
		"idx",
	],

	child_table_field_list: ["parent", "parenttype", "parentfield"],

	core_pagetypes_list: [
		"PageType",
		"PageField",
		"PagePerm",
		"User",
		"Role",
		"Has Role",
		"Page",
		"Module Def",
		"Print Format",
		"Report",
		"Customize Form",
		"Customize Form Field",
		"Property Setter",
		"Custom Field",
		"Client Script",
	],

	restricted_fields: [
		"name",
		"parent",
		"creation",
		"modified",
		"modified_by",
		"parentfield",
		"parenttype",
		"file_list",
		"flags",
		"pagestatus",
	],

	html_fieldtypes: [
		"Text Editor",
		"Text",
		"Small Text",
		"Long Text",
		"HTML Editor",
		"Markdown Editor",
		"Code",
		"Jeditor",
	],

	std_fields: [
		{ fieldname: "name", fieldtype: "Link", label: __("ID") },
		{ fieldname: "owner", fieldtype: "Link", label: __("Created By"), options: "User" },
		{ fieldname: "idx", fieldtype: "Int", label: __("Index") },
		{ fieldname: "creation", fieldtype: "Datetime", label: __("Created On") },
		{ fieldname: "modified", fieldtype: "Datetime", label: __("Last Updated On") },
		{
			fieldname: "modified_by",
			fieldtype: "Link",
			label: __("Last Updated By"),
			options: "User",
		},
		{ fieldname: "_user_tags", fieldtype: "Data", label: __("Tags") },
		{ fieldname: "_liked_by", fieldtype: "Data", label: __("Liked By") },
		{ fieldname: "_comments", fieldtype: "Text", label: __("Comments") },
		{ fieldname: "_assign", fieldtype: "Text", label: __("Assigned To") },
		{ fieldname: "pagestatus", fieldtype: "Int", label: __("Document Status") },
	],

	numeric_fieldtypes: ["Int", "Float", "Currency", "Percent", "Duration"],

	std_fields_table: [{ fieldname: "parent", fieldtype: "Data", label: __("Parent") }],

	table_fields: ["Table", "Table MultiSelect"],

	new_names: {},
	events: {},
	user_settings: {},

	init: function () {
		// setup refresh if the document is updated somewhere else
		jingrow.realtime.on("pg_update", function (data) {
			var pg = locals[data.pagetype] && locals[data.pagetype][data.name];

			if (pg) {
				// current document is dirty, show message if its not me
				if (
					jingrow.get_route()[0] === "Form" &&
					cur_frm.pg.pagetype === pg.pagetype &&
					cur_frm.pg.name === pg.name
				) {
					if (data.modified !== cur_frm.pg.modified && !jingrow.ui.form.is_saving) {
						if (!cur_frm.is_dirty()) {
							cur_frm.debounced_reload_pg();
						} else {
							pg.__needs_refresh = true;
							cur_frm.show_conflict_message();
						}
					}
				} else {
					if (!pg.__unsaved) {
						// no local changes, remove from locals
						jingrow.model.remove_from_locals(pg.pagetype, pg.name);
					} else {
						// show message when user navigates back
						pg.__needs_refresh = true;
					}
				}
			}
		});
	},

	is_value_type: function (fieldtype) {
		if (typeof fieldtype == "object") {
			fieldtype = fieldtype.fieldtype;
		}
		// not in no-value type
		return jingrow.model.no_value_type.indexOf(fieldtype) === -1;
	},

	is_non_std_field: function (fieldname) {
		return ![...jingrow.model.std_fields_list, ...jingrow.model.child_table_field_list].includes(
			fieldname
		);
	},

	get_std_field: function (fieldname, ignore = false) {
		var pagefield = $.map(
			[].concat(jingrow.model.std_fields).concat(jingrow.model.std_fields_table),
			function (d) {
				if (d.fieldname == fieldname) return d;
			}
		);
		if (!pagefield.length) {
			//Standard fields are ignored in case of adding columns as a result of groupby
			if (ignore) {
				return { fieldname: fieldname };
			} else {
				jingrow.msgprint(__("Unknown Column: {0}", [fieldname]));
			}
		}
		return pagefield[0];
	},

	get_from_localstorage: function (pagetype) {
		if (localStorage["_pagetype:" + pagetype]) {
			return JSON.parse(localStorage["_pagetype:" + pagetype]);
		}
	},

	set_in_localstorage: function (pagetype, pgs) {
		try {
			localStorage["_pagetype:" + pagetype] = JSON.stringify(pgs);
		} catch (e) {
			// if quota is exceeded, clear local storage and set item
			console.warn("localStorage quota exceeded, clearing pagetype cache");
			jingrow.model.clear_local_storage();
			localStorage["_pagetype:" + pagetype] = JSON.stringify(pgs);
		}
	},

	clear_local_storage: function () {
		for (var key in localStorage) {
			if (key.startsWith("_pagetype:")) {
				localStorage.removeItem(key);
			}
		}
	},

	with_pagetype: function (pagetype, callback, async) {
		if (locals.PageType[pagetype]) {
			callback && callback();
			return Promise.resolve();
		} else {
			let cached_timestamp = null;
			let cached_pg = null;

			let cached_pgs = jingrow.model.get_from_localstorage(pagetype);

			if (cached_pgs) {
				cached_pg = cached_pgs.filter((pg) => pg.name === pagetype)[0];
				if (cached_pg) {
					cached_timestamp = cached_pg.modified;
				}
			}

			return jingrow.call({
				method: "jingrow.desk.form.load.getpagetype",
				type: "GET",
				args: {
					pagetype: pagetype,
					with_parent: 1,
					cached_timestamp: cached_timestamp,
				},
				async: async,
				callback: function (r) {
					if (r.exc) {
						jingrow.msgprint(__("Unable to load: {0}", [__(pagetype)]));
						throw "No pagetype";
					}
					if (r.message == "use_cache") {
						jingrow.model.sync(cached_pg);
					} else {
						jingrow.model.set_in_localstorage(pagetype, r.pgs);
					}
					jingrow.model.init_pagetype(pagetype);

					if (r.user_settings) {
						// remember filters and other settings from last view
						jingrow.model.user_settings[pagetype] = JSON.parse(r.user_settings);
						jingrow.model.user_settings[pagetype].updated_on = moment().toString();
					}
					callback && callback(r);
				},
			});
		}
	},

	init_pagetype: function (pagetype) {
		var meta = locals.PageType[pagetype];
		for (const asset_key of [
			"__list_js",
			"__custom_list_js",
			"__calendar_js",
			"__map_js",
			"__tree_js",
		]) {
			if (meta[asset_key]) {
				new Function(meta[asset_key])();
			}
		}

		if (meta.__templates) {
			$.extend(jingrow.templates, meta.__templates);
		}
	},

	with_pg: function (pagetype, name, callback) {
		return new Promise((resolve) => {
			if (!name) name = pagetype; // single type
			if (
				locals[pagetype] &&
				locals[pagetype][name] &&
				jingrow.model.get_pageinfo(pagetype, name)
			) {
				callback && callback(name);
				resolve(jingrow.get_pg(pagetype, name));
			} else {
				return jingrow.call({
					method: "jingrow.desk.form.load.getpage",
					type: "GET",
					args: {
						pagetype: pagetype,
						name: name,
					},
					callback: function (r) {
						callback && callback(name, r);
						resolve(jingrow.get_pg(pagetype, name));
					},
				});
			}
		});
	},

	get_pageinfo: function (pagetype, name) {
		return (jingrow.model.pageinfo[pagetype] && jingrow.model.pageinfo[pagetype][name]) || null;
	},

	set_pageinfo: function (pagetype, name, key, value) {
		if (jingrow.model.pageinfo[pagetype] && jingrow.model.pageinfo[pagetype][name]) {
			jingrow.model.pageinfo[pagetype][name][key] = value;
		}
	},

	get_shared: function (pagetype, name) {
		return jingrow.model.get_pageinfo(pagetype, name).shared;
	},

	get_server_module_name: function (pagetype) {
		var dt = jingrow.model.scrub(pagetype);
		var module = jingrow.model.scrub(locals.PageType[pagetype].module);
		var app = jingrow.boot.module_app[module];
		return app + "." + module + ".pagetype." + dt + "." + dt;
	},

	scrub: function (txt) {
		return txt.replace(/ /g, "_").toLowerCase(); // use to slugify or create a slug, a "code-friendly" string
	},

	unscrub: function (txt) {
		return (txt || "").replace(/-|_/g, " ").replace(/\w*/g, function (keywords) {
			return keywords.charAt(0).toUpperCase() + keywords.substr(1).toLowerCase();
		});
	},

	can_create: function (pagetype) {
		return jingrow.boot.user.can_create.indexOf(pagetype) !== -1;
	},

	can_select: function (pagetype) {
		if (jingrow.boot.user) {
			return jingrow.boot.user.can_select.indexOf(pagetype) !== -1;
		}
	},

	can_read: function (pagetype) {
		if (jingrow.boot.user) {
			return jingrow.boot.user.can_read.indexOf(pagetype) !== -1;
		}
	},

	can_write: function (pagetype) {
		return jingrow.boot.user.can_write.indexOf(pagetype) !== -1;
	},

	can_get_report: function (pagetype) {
		return jingrow.boot.user.can_get_report.indexOf(pagetype) !== -1;
	},

	can_delete: function (pagetype) {
		if (!pagetype) return false;
		return jingrow.boot.user.can_delete.indexOf(pagetype) !== -1;
	},

	can_submit: function (pagetype) {
		if (!pagetype) return false;
		return jingrow.boot.user.can_submit.indexOf(pagetype) !== -1;
	},

	can_cancel: function (pagetype) {
		if (!pagetype) return false;
		return jingrow.boot.user.can_cancel.indexOf(pagetype) !== -1;
	},

	has_workflow: function (pagetype) {
		return jingrow.get_list("Workflow", { document_type: pagetype, is_active: 1 }).length;
	},

	is_submittable: function (pagetype) {
		if (!pagetype) return false;
		return locals.PageType[pagetype] && locals.PageType[pagetype].is_submittable;
	},

	is_table: function (pagetype) {
		if (!pagetype) return false;
		return locals.PageType[pagetype] && locals.PageType[pagetype].istable;
	},

	is_single: function (pagetype) {
		if (!pagetype) return false;
		return jingrow.boot.single_types.indexOf(pagetype) != -1;
	},

	is_tree: function (pagetype) {
		if (!pagetype) return false;
		return locals.PageType[pagetype] && locals.PageType[pagetype].is_tree;
	},

	is_fresh(pg) {
		// returns true if document has been recently loaded (5 seconds ago)
		return pg && pg.__last_sync_on && new Date() - pg.__last_sync_on < 5000;
	},

	can_import: function (pagetype, frm, meta = null) {
		if (meta && !meta.allow_import) return false;

		// system manager can always import
		if (jingrow.user_roles.includes("System Manager")) return true;

		if (frm) return frm.perm[0].import === 1;
		return jingrow.boot.user.can_import.indexOf(pagetype) !== -1;
	},

	can_export: function (pagetype, frm) {
		// system manager can always export
		if (jingrow.user_roles.includes("System Manager")) return true;

		if (frm) return frm.perm[0].export === 1;
		return jingrow.boot.user.can_export.indexOf(pagetype) !== -1;
	},

	can_print: function (pagetype, frm) {
		if (frm) return frm.perm[0].print === 1;
		return jingrow.boot.user.can_print.indexOf(pagetype) !== -1;
	},

	can_email: function (pagetype, frm) {
		if (frm) return frm.perm[0].email === 1;
		return jingrow.boot.user.can_email.indexOf(pagetype) !== -1;
	},

	can_share: function (pagetype, frm) {
		let disable_sharing = cint(jingrow.sys_defaults.disable_document_sharing);

		if (disable_sharing && jingrow.session.user !== "Administrator") {
			return false;
		}

		if (frm) {
			return frm.perm[0].share === 1;
		}
		return jingrow.boot.user.can_share.indexOf(pagetype) !== -1;
	},

	has_value: function (dt, dn, fn) {
		// return true if property has value
		var val = locals[dt] && locals[dt][dn] && locals[dt][dn][fn];
		var df = jingrow.meta.get_pagefield(dt, fn, dn);

		let ret;
		if (jingrow.model.table_fields.includes(df.fieldtype)) {
			ret = false;
			$.each(locals[df.options] || {}, function (k, d) {
				if (d.parent == dn && d.parenttype == dt && d.parentfield == df.fieldname) {
					ret = true;
					return false;
				}
			});
		} else {
			ret = !is_null(val);
		}
		return ret ? true : false;
	},

	get_list: function (pagetype, filters) {
		var pgsdict = locals[pagetype] || locals[":" + pagetype] || {};
		if ($.isEmptyObject(pgsdict)) return [];
		return jingrow.utils.filter_dict(pgsdict, filters);
	},

	get_value: function (pagetype, filters, fieldname, callback) {
		if (callback) {
			jingrow.call({
				method: "jingrow.client.get_value",
				args: {
					pagetype: pagetype,
					fieldname: fieldname,
					filters: filters,
				},
				callback: function (r) {
					if (!r.exc) {
						callback(r.message);
					}
				},
			});
		} else {
			if (
				["number", "string"].includes(typeof filters) &&
				locals[pagetype] &&
				locals[pagetype][filters]
			) {
				return locals[pagetype][filters][fieldname];
			} else {
				var l = jingrow.get_list(pagetype, filters);
				return l.length && l[0] ? l[0][fieldname] : null;
			}
		}
	},

	set_value: function (
		pagetype,
		pagename,
		fieldname,
		value,
		fieldtype,
		skip_dirty_trigger = false
	) {
		/* help: Set a value locally (if changed) and execute triggers */

		var pg;
		if ($.isPlainObject(pagetype)) {
			// first parameter is the pg, shift parameters to the left
			pg = pagetype;
			fieldname = pagename;
			value = fieldname;
		} else {
			pg = locals[pagetype] && locals[pagetype][pagename];
		}

		let to_update = fieldname;
		let tasks = [];
		if (!$.isPlainObject(to_update)) {
			to_update = {};
			to_update[fieldname] = value;
		}

		$.each(to_update, (key, value) => {
			if (pg && pg[key] !== value) {
				if (pg.__unedited && !(!pg[key] && !value)) {
					// unset unedited flag for virgin rows
					pg.__unedited = false;
				}

				pg[key] = value;
				tasks.push(() => jingrow.model.trigger(key, value, pg, skip_dirty_trigger));
			} else {
				// execute link triggers (want to reselect to execute triggers)
				if (["Link", "Dynamic Link"].includes(fieldtype) && pg) {
					tasks.push(() => jingrow.model.trigger(key, value, pg, skip_dirty_trigger));
				}
			}
		});

		return jingrow.run_serially(tasks);
	},

	on: function (pagetype, fieldname, fn) {
		/* help: Attach a trigger on change of a particular field.
		To trigger on any change in a particular pagetype, use fieldname as "*"
		*/
		/* example: jingrow.model.on("Customer", "age", function(fieldname, value, pg) {
		  if(pg.age < 16) {
		   	jingrow.msgprint("Warning, Customer must atleast be 16 years old.");
		    raise "CustomerAgeError";
		  }
		}) */
		jingrow.provide("jingrow.model.events." + pagetype);
		if (!jingrow.model.events[pagetype][fieldname]) {
			jingrow.model.events[pagetype][fieldname] = [];
		}
		jingrow.model.events[pagetype][fieldname].push(fn);
	},

	trigger: function (fieldname, value, pg, skip_dirty_trigger = false) {
		const tasks = [];

		function enqueue_events(events) {
			if (!events) return;

			for (const fn of events) {
				if (!fn) continue;

				tasks.push(() => {
					const return_value = fn(fieldname, value, pg, skip_dirty_trigger);

					// if the trigger returns a promise, return it,
					// or use the default promise jingrow.after_ajax
					if (return_value && return_value.then) {
						return return_value;
					} else {
						return jingrow.after_server_call();
					}
				});
			}
		}

		if (jingrow.model.events[pg.pagetype]) {
			enqueue_events(jingrow.model.events[pg.pagetype][fieldname]);
			enqueue_events(jingrow.model.events[pg.pagetype]["*"]);
		}

		return jingrow.run_serially(tasks);
	},

	get_pg: function (pagetype, name) {
		if (!name) name = pagetype;
		if ($.isPlainObject(name)) {
			var pg = jingrow.get_list(pagetype, name);
			return pg && pg.length ? pg[0] : null;
		}
		return locals[pagetype] ? locals[pagetype][name] : null;
	},

	get_children: function (pagetype, parent, parentfield, filters) {
		let pg;
		if ($.isPlainObject(pagetype)) {
			pg = pagetype;
			filters = parentfield;
			parentfield = parent;
		} else {
			pg = jingrow.get_pg(pagetype, parent);
		}

		var children = pg[parentfield] || [];
		if (filters) {
			return jingrow.utils.filter_dict(children, filters);
		} else {
			return children;
		}
	},

	clear_table: function (pg, parentfield) {
		for (const d of pg[parentfield] || []) {
			delete locals[d.pagetype][d.name];
		}
		pg[parentfield] = [];
	},

	remove_from_locals: function (pagetype, name) {
		this.clear_pg(pagetype, name);
		if (jingrow.views.formview[pagetype]) {
			delete jingrow.views.formview[pagetype].frm.openpgs[name];
		}
	},

	clear_pg: function (pagetype, name) {
		var pg = locals[pagetype] && locals[pagetype][name];
		if (!pg) return;

		var parent = null;
		if (pg.parenttype) {
			parent = pg.parent;
			var parenttype = pg.parenttype,
				parentfield = pg.parentfield;
		}
		delete locals[pagetype][name];
		if (parent) {
			var parent_pg = locals[parenttype][parent];
			var newlist = [],
				idx = 1;
			$.each(parent_pg[parentfield], function (i, d) {
				if (d.name != name) {
					newlist.push(d);
					d.idx = idx;
					idx++;
				}
				parent_pg[parentfield] = newlist;
			});
		}
	},

	get_no_copy_list: function (pagetype) {
		var no_copy_list = ["name", "amended_from", "amendment_date", "cancel_reason"];

		var pagefields = jingrow.get_pg("PageType", pagetype).fields || [];
		for (var i = 0, j = pagefields.length; i < j; i++) {
			var df = pagefields[i];
			if (cint(df.no_copy)) no_copy_list.push(df.fieldname);
		}

		return no_copy_list;
	},

	delete_pg: function (pagetype, pagename, callback) {
		let title = pagename;
		const title_field = jingrow.get_meta(pagetype).title_field;
		if (jingrow.get_meta(pagetype).autoname == "hash" && title_field) {
			const value = jingrow.model.get_value(pagetype, pagename, title_field);
			if (value) {
				title = `${value} (${pagename})`;
			}
		}
		jingrow.confirm(__("Permanently delete {0}?", [title.bold()]), function () {
			return jingrow.call({
				method: "jingrow.client.delete",
				args: {
					pagetype: pagetype,
					name: pagename,
				},
				freeze: true,
				freeze_message: __("Deleting {0}...", [title]),
				callback: function (r, rt) {
					if (!r.exc) {
						jingrow.utils.play_sound("delete");
						jingrow.model.clear_pg(pagetype, pagename);
						if (callback) callback(r, rt);
					}
				},
			});
		});
	},

	rename_pg: function (pagetype, pagename, callback) {
		let message = __("Merge with existing");
		let warning = __("This cannot be undone");
		let merge_label = message + " <b>(" + warning + ")</b>";

		var d = new jingrow.ui.Dialog({
			title: __("Rename {0}", [__(pagename)]),
			fields: [
				{
					label: __("New Name"),
					fieldname: "new_name",
					fieldtype: "Data",
					reqd: 1,
					default: pagename,
				},
				{ label: merge_label, fieldtype: "Check", fieldname: "merge" },
			],
		});

		d.set_primary_action(__("Rename"), function () {
			d.hide();
			var args = d.get_values();
			if (!args) return;
			return jingrow.call({
				method: "jingrow.rename_pg",
				freeze: true,
				freeze_message: "Updating related fields...",
				args: {
					pagetype: pagetype,
					old: pagename,
					new: args.new_name,
					merge: args.merge,
				},
				btn: d.get_primary_btn(),
				callback: function (r, rt) {
					if (!r.exc) {
						$(document).trigger("rename", [
							pagetype,
							pagename,
							r.message || args.new_name,
						]);
						if (locals[pagetype] && locals[pagetype][pagename])
							delete locals[pagetype][pagename];
						d.hide();
						if (callback) callback(r.message);
					}
				},
			});
		});
		d.show();
	},

	round_floats_in: function (pg, fieldnames) {
		if (!pg) {
			return;
		}
		if (!fieldnames) {
			fieldnames = jingrow.meta.get_fieldnames(pg.pagetype, pg.parent, {
				fieldtype: ["in", ["Currency", "Float"]],
			});
		}
		for (var i = 0, j = fieldnames.length; i < j; i++) {
			var fieldname = fieldnames[i];
			pg[fieldname] = flt(pg[fieldname], precision(fieldname, pg));
		}
	},

	validate_missing: function (pg, fieldname) {
		if (!pg[fieldname]) {
			jingrow.throw(
				__("Please specify") +
					": " +
					__(jingrow.meta.get_label(pg.pagetype, fieldname, pg.parent || pg.name))
			);
		}
	},

	get_all_pgs: function (pg) {
		var all = [pg];
		for (var key in pg) {
			if ($.isArray(pg[key]) && !key.startsWith("_")) {
				var children = pg[key];
				for (var i = 0, l = children.length; i < l; i++) {
					all.push(children[i]);
				}
			}
		}
		return all;
	},

	get_full_column_name: function (fieldname, pagetype) {
		if (fieldname.includes("`tab")) return fieldname;
		return "`tab" + pagetype + "`.`" + fieldname + "`";
	},

	is_numeric_field: function (fieldtype) {
		if (!fieldtype) return;
		if (typeof fieldtype === "object") {
			fieldtype = fieldtype.fieldtype;
		}
		return jingrow.model.numeric_fieldtypes.includes(fieldtype);
	},

	set_default_views_for_pagetype(pagetype, frm) {
		jingrow.model.with_pagetype(pagetype, () => {
			let meta = jingrow.get_meta(pagetype);
			let default_views = ["List", "Report", "Dashboard", "Kanban"];

			if (meta.is_calendar_and_gantt && jingrow.views.calendar[pagetype]) {
				let views = ["Calendar", "Gantt"];
				default_views.push(...views);
			}

			if (meta.is_tree) {
				default_views.push("Tree");
			}

			if (frm.pg.image_field) {
				default_views.push("Image");
			}

			if (pagetype === "Communication" && jingrow.boot.email_accounts.length) {
				default_views.push("Inbox");
			}

			if (
				(frm.pg.fields?.find((i) => i.fieldname === "latitude") &&
					frm.pg.fields?.find((i) => i.fieldname === "longitude")) ||
				frm.pg.fields?.find(
					(i) => i.fieldname === "location" && i.fieldtype == "Geolocation"
				)
			) {
				default_views.push("Map");
			}

			frm.set_df_property("default_view", "options", default_views);
		});
	},
});

// legacy
jingrow.get_pg = jingrow.model.get_pg;
jingrow.get_children = jingrow.model.get_children;
jingrow.get_list = jingrow.model.get_list;

var getchildren = function (pagetype, parent, parentfield) {
	var children = [];
	$.each(locals[pagetype] || {}, function (i, d) {
		if (d.parent === parent && d.parentfield === parentfield) {
			children.push(d);
		}
	});
	return children;
};
