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

jingrow.provide("jingrow.model");

$.extend(jingrow.model, {
	new_names: {},

	get_new_pg: function (pagetype, parent_pg, parentfield, with_mandatory_children) {
		jingrow.provide("locals." + pagetype);
		var pg = {
			pagestatus: 0,
			pagetype: pagetype,
			name: jingrow.model.get_new_name(pagetype),
			__islocal: 1,
			__unsaved: 1,
			owner: jingrow.session.user,
		};
		jingrow.model.set_default_values(pg, parent_pg);

		if (parent_pg) {
			$.extend(pg, {
				parent: parent_pg.name,
				parentfield: parentfield,
				parenttype: parent_pg.pagetype,
			});
			if (!parent_pg[parentfield]) parent_pg[parentfield] = [];
			pg.idx = parent_pg[parentfield].length + 1;
			parent_pg[parentfield].push(pg);
		} else {
			jingrow.provide("jingrow.model.pageinfo." + pagetype + "." + pg.name);
		}

		jingrow.model.add_to_locals(pg);

		if (with_mandatory_children) {
			jingrow.model.create_mandatory_children(pg);
		}

		if (!parent_pg) {
			pg.__run_link_triggers = 1;
		}

		// set the name if called from a link field
		if (jingrow.route_options && jingrow.route_options.name_field) {
			var meta = jingrow.get_meta(pagetype);
			// set title field / name as name
			if (meta.autoname && meta.autoname.indexOf("field:") !== -1) {
				pg[meta.autoname.substr(6)] = jingrow.route_options.name_field;
			} else if (meta.autoname && meta.autoname === "prompt") {
				pg.__newname = jingrow.route_options.name_field;
			} else if (meta.title_field) {
				pg[meta.title_field] = jingrow.route_options.name_field;
			}

			delete jingrow.route_options.name_field;
		}

		// set route options
		if (jingrow.route_options && !pg.parent) {
			$.each(jingrow.route_options, function (fieldname, value) {
				var df = jingrow.meta.has_field(pagetype, fieldname);
				if (df && !df.no_copy) {
					pg[fieldname] = value;
				}
			});
			jingrow.route_options = null;
		}

		return pg;
	},

	make_new_pg_and_get_name: function (pagetype, with_mandatory_children) {
		return jingrow.model.get_new_pg(pagetype, null, null, with_mandatory_children).name;
	},

	get_new_name: function (pagetype) {
		// random hash is added to idenity mislinked files when pg is not saved and file is uploaded.
		return jingrow.router.slug(`new-${pagetype}-${jingrow.utils.get_random(10)}`);
	},

	set_default_values: function (pg, parent_pg) {
		let pagetype = pg.pagetype;
		let pagefields = jingrow.meta.get_pagefields(pagetype);
		let updated = [];

		// Table types should be initialized
		let fieldtypes_without_default = jingrow.model.no_value_type.filter(
			(fieldtype) => !jingrow.model.table_fields.includes(fieldtype)
		);
		pagefields.forEach((f) => {
			if (
				fieldtypes_without_default.includes(f.fieldtype) ||
				pg[f.fieldname] != null ||
				f.no_default
			) {
				return;
			}

			let v = jingrow.model.get_default_value(f, pg, parent_pg);
			if (v) {
				if (["Int", "Check"].includes(f.fieldtype)) v = cint(v);
				else if (["Currency", "Float"].includes(f.fieldtype)) v = flt(v);

				pg[f.fieldname] = v;
				updated.push(f.fieldname);
			} else if (
				f.fieldtype == "Select" &&
				f.options &&
				typeof f.options === "string" &&
				!["[Select]", "Loading..."].includes(f.options)
			) {
				pg[f.fieldname] = f.options.split("\n")[0];
			}
		});
		return updated;
	},

	create_mandatory_children: function (pg) {
		var meta = jingrow.get_meta(pg.pagetype);
		if (meta && meta.istable) return;

		// create empty rows for mandatory table fields
		jingrow.meta.get_pagefields(pg.pagetype).forEach(function (df) {
			if (df.fieldtype === "Table" && df.reqd) {
				jingrow.model.add_child(pg, df.fieldname);
			}
		});
	},

	get_default_value: function (df, pg, parent_pg) {
		var user_default = "";
		var user_permissions = jingrow.defaults.get_user_permissions();
		let allowed_records = [];
		let default_pg = null;
		let value = null;
		if (user_permissions) {
			({ allowed_records, default_pg } = jingrow.perm.filter_allowed_pgs_for_pagetype(
				user_permissions[df.options],
				pg.pagetype
			));
		}
		var meta = jingrow.get_meta(pg.pagetype);
		var has_user_permissions =
			df.fieldtype === "Link" &&
			!$.isEmptyObject(user_permissions) &&
			df.ignore_user_permissions != 1 &&
			allowed_records.length;

		// don't set defaults for "User" link field using User Permissions!
		if (df.fieldtype === "Link" && df.options !== "User") {
			// If user permission has Is Default enabled or single-user permission has found against respective pagetype.
			if (has_user_permissions && default_pg) {
				value = default_pg;
			} else {
				// 2 - look in user defaults

				if (!df.ignore_user_permissions) {
					var user_defaults = jingrow.defaults.get_user_defaults(df.options);
					if (user_defaults && user_defaults.length === 1) {
						// Use User Permission value when only when it has a single value
						user_default = user_defaults[0];
					}
				}

				if (!user_default) {
					user_default = jingrow.defaults.get_user_default(df.fieldname);
				}
				if (
					!user_default &&
					df.remember_last_selected_value &&
					jingrow.boot.user.last_selected_values
				) {
					user_default = jingrow.boot.user.last_selected_values[df.options];
				}

				var is_allowed_user_default =
					user_default &&
					(!has_user_permissions || allowed_records.includes(user_default));

				// is this user default also allowed as per user permissions?
				if (is_allowed_user_default) {
					value = user_default;
				}
			}
		}

		// 3 - look in default of pagefield
		if (!value || df["default"]) {
			const default_val = String(df["default"]);
			if (default_val == "__user" || default_val.toLowerCase() == "user") {
				value = jingrow.session.user;
			} else if (default_val == "user_fullname") {
				value = jingrow.session.user_fullname;
			} else if (default_val == "Today") {
				value = jingrow.datetime.get_today();
			} else if ((default_val || "").toLowerCase() === "now") {
				if (df.fieldtype == "Time") {
					value = jingrow.datetime.now_time();
				} else {
					// datetime fields are stored in system tz
					value = jingrow.datetime.system_datetime();
				}
			} else if (default_val[0] === ":") {
				var boot_pg = jingrow.model.get_default_from_boot_pgs(df, pg, parent_pg);
				var is_allowed_boot_pg =
					!has_user_permissions || allowed_records.includes(boot_pg);

				if (is_allowed_boot_pg) {
					value = boot_pg;
				}
			} else if (df.fieldname === meta.title_field) {
				// ignore defaults for title field
				value = "";
			} else {
				// is this default value is also allowed as per user permissions?
				var is_allowed_default =
					!has_user_permissions || allowed_records.includes(df.default);
				if (df.fieldtype !== "Link" || df.options === "User" || is_allowed_default) {
					value = df["default"];
				}
			}
		} else if (df.fieldtype == "Time") {
			value = jingrow.datetime.now_time();
		}

		if (jingrow.model.table_fields.includes(df.fieldtype)) {
			value = [];
		}

		// set it here so we know it was set as a default
		df.__default_value = value;

		return value;
	},

	get_default_from_boot_pgs: function (df, pg, parent_pg) {
		// set default from partial pgs passed during boot like ":User"
		if (jingrow.get_list(df["default"]).length > 0) {
			var ref_fieldname = df["default"].slice(1).toLowerCase().replace(" ", "_");
			var ref_value = parent_pg
				? parent_pg[ref_fieldname]
				: jingrow.defaults.get_user_default(ref_fieldname);
			var ref_pg = ref_value ? jingrow.get_pg(df["default"], ref_value) : null;

			if (ref_pg && ref_pg[df.fieldname]) {
				return ref_pg[df.fieldname];
			}
		}
	},

	add_child: function (parent_pg, pagetype, parentfield, idx) {
		// if given pg, fieldname only
		if (arguments.length === 2) {
			parentfield = pagetype;
			pagetype = jingrow.meta.get_field(parent_pg.pagetype, parentfield).options;
		}

		// create row pg
		idx = idx ? idx - 0.1 : (parent_pg[parentfield] || []).length + 1;

		var child = jingrow.model.get_new_pg(pagetype, parent_pg, parentfield);
		child.idx = idx;

		// renum for fraction
		if (idx !== cint(idx)) {
			var sorted = parent_pg[parentfield].sort(function (a, b) {
				return a.idx - b.idx;
			});
			for (var i = 0, j = sorted.length; i < j; i++) {
				var d = sorted[i];
				d.idx = i + 1;
			}
		}

		if (cur_frm && cur_frm.pg == parent_pg) cur_frm.dirty();

		return child;
	},

	copy_pg: function (pg, from_amend, parent_pg, parentfield) {
		let no_copy_list = ["name", "amended_from", "amendment_date", "cancel_reason"];
		let newdoc = jingrow.model.get_new_pg(pg.pagetype, parent_pg, parentfield);

		for (let key in pg) {
			// don't copy name and blank fields
			let df = jingrow.meta.get_pagefield(pg.pagetype, key);

			const is_internal_field = key.substring(0, 2) === "__";
			const is_blocked_field = no_copy_list.includes(key);
			const is_no_copy = !from_amend && df && cint(df.no_copy) == 1;
			const is_password = df && df.fieldtype === "Password";

			if (df && !is_internal_field && !is_blocked_field && !is_no_copy && !is_password) {
				let value = pg[key] || [];
				if (jingrow.model.table_fields.includes(df.fieldtype)) {
					for (let i = 0, j = value.length; i < j; i++) {
						let d = value[i];
						jingrow.model.copy_pg(d, from_amend, newdoc, df.fieldname);
					}
				} else {
					newdoc[key] = pg[key];
				}
			}
		}

		let user = jingrow.session.user;

		newdoc.__islocal = 1;
		newdoc.pagestatus = 0;
		newdoc.owner = user;
		newdoc.creation = "";
		newdoc.modified_by = user;
		newdoc.modified = "";
		newdoc.lft = null;
		newdoc.rgt = null;

		if (from_amend && parent_pg) {
			newdoc._amended_from = pg.name;
		}

		return newdoc;
	},

	open_mapped_pg: function (opts) {
		if (opts.frm && opts.frm.pg.__unsaved) {
			jingrow.throw(
				__("You have unsaved changes in this form. Please save before you continue.")
			);
		} else if (!opts.source_name && opts.frm) {
			opts.source_name = opts.frm.pg.name;
		} else if (!opts.frm && !opts.source_name) {
			opts.source_name = null;
		}

		return jingrow.call({
			type: "POST",
			method: "jingrow.model.mapper.make_mapped_pg",
			args: {
				method: opts.method,
				source_name: opts.source_name,
				args: opts.args || null,
				selected_children: opts.frm ? opts.frm.get_selected() : null,
			},
			freeze: true,
			freeze_message: opts.freeze_message || "",
			callback: function (r) {
				if (!r.exc) {
					jingrow.model.sync(r.message);
					if (opts.run_link_triggers) {
						jingrow.get_pg(
							r.message.pagetype,
							r.message.name
						).__run_link_triggers = true;
					}
					jingrow.set_route("Form", r.message.pagetype, r.message.name);
				}
			},
		});
	},
});

jingrow.create_routes = {};
jingrow.new_pg = function (pagetype, opts, init_callback) {
	if (pagetype === "File") {
		new jingrow.ui.FileUploader({
			folder: opts ? opts.folder : "Home",
		});
		return;
	}
	return new Promise((resolve) => {
		if (opts && $.isPlainObject(opts)) {
			jingrow.route_options = opts;
		}
		jingrow.model.with_pagetype(pagetype, function () {
			if (jingrow.create_routes[pagetype]) {
				jingrow.set_route(jingrow.create_routes[pagetype]).then(() => resolve());
			} else {
				jingrow.ui.form
					.make_quick_entry(pagetype, null, init_callback)
					.then(() => resolve());
			}
		});
	});
};
