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

jingrow.ui.form.save = function (frm, action, callback, btn) {
	$(btn).prop("disabled", true);

	// specified here because there are keyboard shortcuts to save
	const working_label = {
		Save: __("Saving", null, "Freeze message while saving a document"),
		Submit: __("Submitting", null, "Freeze message while submitting a document"),
		Update: __("Updating", null, "Freeze message while updating a document"),
		Amend: __("Amending", null, "Freeze message while amending a document"),
		Cancel: __("Cancelling", null, "Freeze message while cancelling a document"),
	}[toTitle(action)];

	var freeze_message = working_label ? __(working_label) : "";

	var save = function () {
		remove_empty_rows();

		$(frm.wrapper).addClass("validated-form");
		if ((action !== "Save" || frm.is_dirty()) && check_mandatory()) {
			_call({
				method: "jingrow.desk.form.save.savepgs",
				args: { pg: frm.pg, action: action },
				callback: function (r) {
					$(document).trigger("save", [frm.pg]);
					callback(r);
				},
				error: function (r) {
					callback(r);
				},
				btn: btn,
				freeze_message: freeze_message,
			});
		} else {
			!frm.is_dirty() &&
				jingrow.show_alert({ message: __("No changes in document"), indicator: "orange" });
			$(btn).prop("disabled", false);
		}
	};

	var remove_empty_rows = function () {
		/*
			This function removes empty rows. Note that in this function, a row is considered
			empty if the fields with `in_list_view: 1` are undefined or falsy because that's
			what users also consider to be an empty row
		*/
		const pgs = jingrow.model.get_all_pgs(frm.pg);

		// we should only worry about table data
		const tables = pgs.filter((d) => {
			return jingrow.model.is_table(d.pagetype);
		});

		let modified_table_fields = [];

		tables.map((pg) => {
			const cells = jingrow.meta.pagefield_list[pg.pagetype] || [];

			const in_list_view_cells = cells.filter((df) => {
				return cint(df.in_list_view) === 1;
			});

			const is_empty_row = function (cells) {
				for (let i = 0; i < cells.length; i++) {
					if (
						locals[pg.pagetype][pg.name] &&
						locals[pg.pagetype][pg.name][cells[i].fieldname]
					) {
						return false;
					}
				}
				return true;
			};

			if (is_empty_row(in_list_view_cells)) {
				jingrow.model.clear_pg(pg.pagetype, pg.name);
				modified_table_fields.push(pg.parentfield);
			}
		});

		modified_table_fields.forEach((field) => {
			frm.refresh_field(field);
		});
	};

	var cancel = function () {
		var args = {
			pagetype: frm.pg.pagetype,
			name: frm.pg.name,
		};

		// update workflow state value if workflow exists
		var workflow_state_fieldname = jingrow.workflow.get_state_fieldname(frm.pagetype);
		if (workflow_state_fieldname) {
			$.extend(args, {
				workflow_state_fieldname: workflow_state_fieldname,
				workflow_state: frm.pg[workflow_state_fieldname],
			});
		}

		_call({
			method: "jingrow.desk.form.save.cancel",
			args: args,
			callback: function (r) {
				$(document).trigger("save", [frm.pg]);
				callback(r);
			},
			btn: btn,
			freeze_message: freeze_message,
		});
	};

	var check_mandatory = function () {
		var has_errors = false;
		frm.scroll_set = false;

		if (frm.pg.pagestatus == 2) return true; // don't check for cancel

		$.each(jingrow.model.get_all_pgs(frm.pg), function (i, pg) {
			var error_fields = [];
			var folded = false;

			$.each(jingrow.meta.pagefield_list[pg.pagetype] || [], function (i, pagefield) {
				if (pagefield.fieldname) {
					const df = jingrow.meta.get_pagefield(pg.pagetype, pagefield.fieldname, pg.name);

					if (df.fieldtype === "Fold") {
						folded = frm.layout.folded;
					}

					if (
						is_pagefield_mandatory(pg, df) &&
						!jingrow.model.has_value(pg.pagetype, pg.name, df.fieldname)
					) {
						has_errors = true;
						error_fields[error_fields.length] = __(df.label, null, df.parent);
						// scroll to field
						if (!frm.scroll_set) {
							scroll_to(pg.parentfield || df.fieldname);
						}

						if (folded) {
							frm.layout.unfold();
							folded = false;
						}
					}
				}
			});

			if (frm.is_new() && frm.meta.autoname === "Prompt" && !frm.pg.__newname) {
				has_errors = true;
				error_fields = [__("Name"), ...error_fields];
			}

			if (error_fields.length) {
				let meta = jingrow.get_meta(pg.pagetype);
				let message;
				if (meta.istable) {
					const table_field = jingrow.meta.pagefield_map[pg.parenttype][pg.parentfield];

					const table_label = __(
						table_field.label || jingrow.unscrub(table_field.fieldname)
					).bold();

					message = __("Mandatory fields required in table {0}, Row {1}", [
						table_label,
						pg.idx,
					]);
				} else {
					message = __("Mandatory fields required in {0}", [__(pg.pagetype)]);
				}
				message = message + "<br><br><ul><li>" + error_fields.join("</li><li>") + "</ul>";
				jingrow.msgprint({
					message: message,
					indicator: "red",
					title: __("Missing Fields"),
				});
				frm.refresh();
			}
		});

		return !has_errors;
	};

	let is_pagefield_mandatory = function (pg, df) {
		if (df.reqd) return true;
		if (!df.mandatory_depends_on || !pg) return;

		let out = null;
		let expression = df.mandatory_depends_on;
		let parent = jingrow.get_meta(df.parent);

		if (typeof expression === "boolean") {
			out = expression;
		} else if (typeof expression === "function") {
			out = expression(pg);
		} else if (expression.substr(0, 5) == "eval:") {
			try {
				out = jingrow.utils.eval(expression.substr(5), { pg, parent });
				if (parent && parent.istable && expression.includes("is_submittable")) {
					out = true;
				}
			} catch (e) {
				jingrow.throw(__('Invalid "mandatory_depends_on" expression'));
			}
		} else {
			var value = pg[expression];
			if ($.isArray(value)) {
				out = !!value.length;
			} else {
				out = !!value;
			}
		}

		return out;
	};

	const scroll_to = (fieldname) => {
		frm.scroll_to_field(fieldname);
		frm.scroll_set = true;
	};

	var _call = function (opts) {
		// opts = {
		// 	method: "some server method",
		// 	args: {args to be passed},
		// 	callback: callback,
		// 	btn: btn
		// }

		if (jingrow.ui.form.is_saving) {
			// this is likely to happen if the user presses the shortcut cmd+s for a longer duration or uses double click
			// no need to show this to user, as they can see "Saving" in freeze message
			console.log("Already saving. Please wait a few moments.");
			throw "saving";
		}

		// ensure we remove new pgs routes ONLY
		if (frm.is_new()) {
			jingrow.ui.form.remove_old_form_route();
		}
		jingrow.ui.form.is_saving = true;

		return jingrow.call({
			freeze: true,
			// freeze_message: opts.freeze_message,
			method: opts.method,
			args: opts.args,
			btn: opts.btn,
			callback: function (r) {
				opts.callback && opts.callback(r);
			},
			error: opts.error,
			always: function (r) {
				$(btn).prop("disabled", false);
				jingrow.ui.form.is_saving = false;

				if (r) {
					var pg = r.pgs && r.pgs[0];
					if (pg) {
						jingrow.ui.form.update_calling_link(pg);
					}
				}
			},
		});
	};

	if (action === "cancel") {
		cancel();
	} else {
		save();
	}
};

jingrow.ui.form.remove_old_form_route = () => {
	let current_route = jingrow.get_route().join("/");
	jingrow.route_history = jingrow.route_history.filter(
		(route) => route.join("/") !== current_route
	);
};

jingrow.ui.form.update_calling_link = (newdoc) => {
	if (!jingrow._from_link) return;
	var pg = jingrow.get_pg(jingrow._from_link.pagetype, jingrow._from_link.pagename);

	let is_valid_pagetype = () => {
		if (jingrow._from_link.df.fieldtype === "Link") {
			return newdoc.pagetype === jingrow._from_link.df.options;
		} else {
			// dynamic link, type is dynamic
			return newdoc.pagetype === pg[jingrow._from_link.df.options];
		}
	};

	if (is_valid_pagetype()) {
		jingrow.model.with_pagetype(newdoc.pagetype, () => {
			let meta = jingrow.get_meta(newdoc.pagetype);
			// set value
			if (pg && pg.parentfield) {
				//update values for child table
				$.each(
					jingrow._from_link.frm.fields_dict[pg.parentfield].grid.grid_rows,
					function (index, field) {
						if (field.pg && field.pg.name === jingrow._from_link.pagename) {
							if (meta.title_field && meta.show_title_field_in_link) {
								jingrow.utils.add_link_title(
									newdoc.pagetype,
									newdoc.name,
									newdoc[meta.title_field]
								);
							}
							jingrow._from_link.set_value(newdoc.name);
						}
					}
				);
			} else {
				if (meta.title_field && meta.show_title_field_in_link) {
					jingrow.utils.add_link_title(
						newdoc.pagetype,
						newdoc.name,
						newdoc[meta.title_field]
					);
				}
				jingrow._from_link.set_value(newdoc.name);
			}

			// refresh field
			jingrow._from_link.refresh();

			// if from form, switch
			if (jingrow._from_link.frm) {
				jingrow
					.set_route(
						"Form",
						jingrow._from_link.frm.pagetype,
						jingrow._from_link.frm.pagename
					)
					.then(() => {
						jingrow.utils.scroll_to(jingrow._from_link_scrollY);
					});
			}

			jingrow._from_link = null;
		});
	}
};
