// Copyright (c) 2015, JINGROW and Contributors
// MIT License. See license.txt
/* eslint-disable no-console */

// __('Modules') __('Domains') __('Places') __('Administration') # for translation, don't remove

jingrow.start_app = function () {
	if (!jingrow.Application) return;
	jingrow.assets.check();
	jingrow.provide("jingrow.app");
	jingrow.provide("jingrow.desk");
	jingrow.app = new jingrow.Application();
};

$(document).ready(function () {
	if (!jingrow.utils.supportsES6) {
		jingrow.msgprint({
			indicator: "red",
			title: __("Browser not supported"),
			message: __(
				"Some of the features might not work in your browser. Please update your browser to the latest version."
			),
		});
	}
	jingrow.start_app();
});

jingrow.Application = class Application {
	constructor() {
		this.startup();
	}

	startup() {
		jingrow.realtime.init();
		jingrow.model.init();

		this.load_bootinfo();
		this.load_user_permissions();
		this.make_nav_bar();
		this.set_favicon();
		this.set_fullwidth_if_enabled();
		this.add_browser_class();
		this.setup_energy_point_listeners();
		this.setup_copy_pg_listener();
		this.setup_broadcast_listeners();

		jingrow.ui.keys.setup();

		jingrow.ui.keys.add_shortcut({
			shortcut: "shift+ctrl+g",
			description: __("Switch Theme"),
			action: () => {
				if (jingrow.theme_switcher && jingrow.theme_switcher.dialog.is_visible) {
					jingrow.theme_switcher.hide();
				} else {
					jingrow.theme_switcher = new jingrow.ui.ThemeSwitcher();
					jingrow.theme_switcher.show();
				}
			},
		});

		jingrow.ui.add_system_theme_switch_listener();
		const root = document.documentElement;

		const observer = new MutationObserver(() => {
			jingrow.ui.set_theme();
		});
		observer.observe(root, {
			attributes: true,
			attributeFilter: ["data-theme-mode"],
		});

		jingrow.ui.set_theme();

		// page container
		this.make_page_container();
		if (
			!window.Cypress &&
			jingrow.boot.onboarding_tours &&
			jingrow.boot.user.onboarding_status != null
		) {
			let pending_tours = !jingrow.boot.onboarding_tours.every(
				(tour) => jingrow.boot.user.onboarding_status[tour[0]]?.is_complete
			);
			if (pending_tours && jingrow.boot.onboarding_tours.length > 0) {
				jingrow.require("onboarding_tours.bundle.js", () => {
					jingrow.utils.sleep(1000).then(() => {
						jingrow.ui.init_onboarding_tour();
					});
				});
			}
		}
		this.set_route();

		// trigger app startup
		$(document).trigger("startup");

		$(document).trigger("app_ready");

		if (jingrow.boot.messages) {
			jingrow.msgprint(jingrow.boot.messages);
		}

		if (jingrow.user_roles.includes("System Manager")) {
			// delayed following requests to make boot faster
			setTimeout(() => {
				this.show_change_log();
				this.show_update_available();
			}, 1000);
		}

		if (!jingrow.boot.developer_mode) {
			let console_security_message = __(
				"Using this console may allow attackers to impersonate you and steal your information. Do not enter or paste code that you do not understand."
			);
			console.log(`%c${console_security_message}`, "font-size: large");
		}

		this.show_notes();

		if (jingrow.ui.startup_setup_dialog && !jingrow.boot.setup_complete) {
			jingrow.ui.startup_setup_dialog.pre_show();
			jingrow.ui.startup_setup_dialog.show();
		}

		jingrow.realtime.on("version-update", function () {
			var dialog = jingrow.msgprint({
				message: __(
					"The application has been updated to a new version, please refresh this page"
				),
				indicator: "green",
				title: __("Version Updated"),
			});
			dialog.set_primary_action(__("Refresh"), function () {
				location.reload(true);
			});
			dialog.get_close_btn().toggle(false);
		});

		// listen to build errors
		this.setup_build_events();

		if (jingrow.sys_defaults.email_user_password) {
			var email_list = jingrow.sys_defaults.email_user_password.split(",");
			for (var u in email_list) {
				if (email_list[u] === jingrow.user.name) {
					this.set_password(email_list[u]);
				}
			}
		}

		// REDESIGN-TODO: Fix preview popovers
		this.link_preview = new jingrow.ui.LinkPreview();

		jingrow.broadcast.emit("boot", {
			csrf_token: jingrow.csrf_token,
			user: jingrow.session.user,
		});
	}

	set_route() {
		if (jingrow.boot && localStorage.getItem("session_last_route")) {
			jingrow.set_route(localStorage.getItem("session_last_route"));
			localStorage.removeItem("session_last_route");
		} else {
			// route to home page
			jingrow.router.route();
		}
		jingrow.router.on("change", () => {
			$(".tooltip").hide();
		});
	}

	set_password(user) {
		var me = this;
		jingrow.call({
			method: "jingrow.core.pagetype.user.user.get_email_awaiting",
			args: {
				user: user,
			},
			callback: function (email_account) {
				email_account = email_account["message"];
				if (email_account) {
					var i = 0;
					if (i < email_account.length) {
						me.email_password_prompt(email_account, user, i);
					}
				}
			},
		});
	}

	email_password_prompt(email_account, user, i) {
		var me = this;
		const email_id = email_account[i]["email_id"];
		let d = new jingrow.ui.Dialog({
			title: __("Password missing in Email Account"),
			fields: [
				{
					fieldname: "password",
					fieldtype: "Password",
					label: __(
						"Please enter the password for: <b>{0}</b>",
						[email_id],
						"Email Account"
					),
					reqd: 1,
				},
				{
					fieldname: "submit",
					fieldtype: "Button",
					label: __("Submit", null, "Submit password for Email Account"),
				},
			],
		});
		d.get_input("submit").on("click", function () {
			//setup spinner
			d.hide();
			var s = new jingrow.ui.Dialog({
				title: __("Checking one moment"),
				fields: [
					{
						fieldtype: "HTML",
						fieldname: "checking",
					},
				],
			});
			s.fields_dict.checking.$wrapper.html('<i class="fa fa-spinner fa-spin fa-4x"></i>');
			s.show();
			jingrow.call({
				method: "jingrow.email.pagetype.email_account.email_account.set_email_password",
				args: {
					email_account: email_account[i]["email_account"],
					password: d.get_value("password"),
				},
				callback: function (passed) {
					s.hide();
					d.hide(); //hide waiting indication
					if (!passed["message"]) {
						jingrow.show_alert(
							{ message: __("Login Failed please try again"), indicator: "error" },
							5
						);
						me.email_password_prompt(email_account, user, i);
					} else {
						if (i + 1 < email_account.length) {
							i = i + 1;
							me.email_password_prompt(email_account, user, i);
						}
					}
				},
			});
		});
		d.show();
	}
	load_bootinfo() {
		if (jingrow.boot) {
			this.setup_workspaces();
			jingrow.model.sync(jingrow.boot.pgs);
			this.check_metadata_cache_status();
			this.set_globals();
			this.sync_pages();
			jingrow.router.setup();
			this.setup_moment();
			if (jingrow.boot.print_css) {
				jingrow.dom.set_style(jingrow.boot.print_css, "print-style");
			}
			jingrow.user.name = jingrow.boot.user.name;
			jingrow.router.setup();
		} else {
			this.set_as_guest();
		}
	}

	setup_workspaces() {
		jingrow.modules = {};
		jingrow.workspaces = {};
		for (let page of jingrow.boot.allowed_workspaces || []) {
			jingrow.modules[page.module] = page;
			jingrow.workspaces[jingrow.router.slug(page.name)] = page;
		}
	}

	load_user_permissions() {
		jingrow.defaults.load_user_permission_from_boot();

		jingrow.realtime.on(
			"update_user_permissions",
			jingrow.utils.debounce(() => {
				jingrow.defaults.update_user_permissions();
			}, 500)
		);
	}

	check_metadata_cache_status() {
		if (jingrow.boot.metadata_version != localStorage.metadata_version) {
			jingrow.assets.clear_local_storage();
			jingrow.assets.init_local_storage();
		}
	}

	set_globals() {
		jingrow.session.user = jingrow.boot.user.name;
		jingrow.session.logged_in_user = jingrow.boot.user.name;
		jingrow.session.user_email = jingrow.boot.user.email;
		jingrow.session.user_fullname = jingrow.user_info().fullname;

		jingrow.user_defaults = jingrow.boot.user.defaults;
		jingrow.user_roles = jingrow.boot.user.roles;
		jingrow.sys_defaults = jingrow.boot.sysdefaults;

		jingrow.ui.py_date_format = jingrow.boot.sysdefaults.date_format
			.replace("dd", "%d")
			.replace("mm", "%m")
			.replace("yyyy", "%Y");
		jingrow.boot.user.last_selected_values = {};
	}
	sync_pages() {
		// clear cached pages if timestamp is not found
		if (localStorage["page_info"]) {
			jingrow.boot.allowed_pages = [];
			var page_info = JSON.parse(localStorage["page_info"]);
			$.each(jingrow.boot.page_info, function (name, p) {
				if (!page_info[name] || page_info[name].modified != p.modified) {
					delete localStorage["_page:" + name];
				}
				jingrow.boot.allowed_pages.push(name);
			});
		} else {
			jingrow.boot.allowed_pages = Object.keys(jingrow.boot.page_info);
		}
		localStorage["page_info"] = JSON.stringify(jingrow.boot.page_info);
	}
	set_as_guest() {
		jingrow.session.user = "Guest";
		jingrow.session.user_email = "";
		jingrow.session.user_fullname = "Guest";

		jingrow.user_defaults = {};
		jingrow.user_roles = ["Guest"];
		jingrow.sys_defaults = {};
	}
	make_page_container() {
		if ($("#body").length) {
			$(".splash").remove();
			jingrow.temp_container = $("<div id='temp-container' style='display: none;'>").appendTo(
				"body"
			);
			jingrow.container = new jingrow.views.Container();
		}
	}
	make_nav_bar() {
		// toolbar
		if (jingrow.boot && jingrow.boot.home_page !== "setup-wizard") {
			jingrow.jingrow_toolbar = new jingrow.ui.toolbar.Toolbar();
		}
	}
	logout() {
		var me = this;
		me.logged_out = true;
		return jingrow.call({
			method: "logout",
			callback: function (r) {
				if (r.exc) {
					return;
				}
				me.redirect_to_login();
			},
		});
	}
	handle_session_expired() {
		jingrow.app.redirect_to_login();
	}
	redirect_to_login() {
		window.location.href = `/login?redirect-to=${encodeURIComponent(
			window.location.pathname + window.location.search
		)}`;
	}
	set_favicon() {
		var link = $('link[type="image/x-icon"]').remove().attr("href");
		$('<link rel="shortcut icon" href="' + link + '" type="image/x-icon">').appendTo("head");
		$('<link rel="icon" href="' + link + '" type="image/x-icon">').appendTo("head");
	}
	trigger_primary_action() {
		// to trigger change event on active input before triggering primary action
		$(document.activeElement).blur();
		// wait for possible JS validations triggered after blur (it might change primary button)
		setTimeout(() => {
			if (window.cur_dialog && cur_dialog.display && !cur_dialog.is_minimized) {
				// trigger primary
				cur_dialog.get_primary_btn().trigger("click");
			} else if (cur_frm && cur_frm.page.btn_primary.is(":visible")) {
				cur_frm.page.btn_primary.trigger("click");
			} else if (jingrow.container.page.save_action) {
				jingrow.container.page.save_action();
			}
		}, 100);
	}

	show_change_log() {
		var me = this;
		let change_log = jingrow.boot.change_log;

		// jingrow.boot.change_log = [{
		// 	"change_log": [
		// 		[<version>, <change_log in markdown>],
		// 		[<version>, <change_log in markdown>],
		// 	],
		// 	"description": "ERP made simple",
		// 	"title": "JERP",
		// 	"version": "12.2.0"
		// }];

		if (
			!Array.isArray(change_log) ||
			!change_log.length ||
			window.Cypress ||
			cint(jingrow.boot.sysdefaults.disable_change_log_notification)
		) {
			return;
		}

		// Iterate over changelog
		var change_log_dialog = jingrow.msgprint({
			message: jingrow.render_template("change_log", { change_log: change_log }),
			title: __("Updated To A New Version 🎉"),
			wide: true,
		});
		change_log_dialog.keep_open = true;
		change_log_dialog.custom_onhide = function () {
			jingrow.call({
				method: "jingrow.utils.change_log.update_last_known_versions",
			});
			me.show_notes();
		};
	}

	show_update_available() {
		if (!jingrow.boot.has_app_updates) return;
		jingrow.xcall("jingrow.utils.change_log.show_update_popup");
	}

	add_browser_class() {
		$("html").addClass(jingrow.utils.get_browser().name.toLowerCase());
	}

	set_fullwidth_if_enabled() {
		jingrow.ui.toolbar.set_fullwidth_if_enabled();
	}

	show_notes() {
		var me = this;
		if (jingrow.boot.notes.length) {
			jingrow.boot.notes.forEach(function (note) {
				if (!note.seen || note.notify_on_every_login) {
					var d = jingrow.msgprint({ message: note.content, title: note.title });
					d.keep_open = true;
					d.custom_onhide = function () {
						note.seen = true;

						// Mark note as read if the Notify On Every Login flag is not set
						if (!note.notify_on_every_login) {
							jingrow.call({
								method: "jingrow.desk.pagetype.note.note.mark_as_seen",
								args: {
									note: note.name,
								},
							});
						}

						// next note
						me.show_notes();
					};
				}
			});
		}
	}

	setup_build_events() {
		if (jingrow.boot.developer_mode) {
			jingrow.require("build_events.bundle.js");
		}
	}

	setup_energy_point_listeners() {
		jingrow.realtime.on("energy_point_alert", (message) => {
			jingrow.show_alert(message);
		});
	}

	setup_copy_pg_listener() {
		$("body").on("paste", (e) => {
			try {
				let pasted_data = jingrow.utils.get_clipboard_data(e);
				let pg = JSON.parse(pasted_data);
				if (pg.pagetype) {
					e.preventDefault();
					const sleep = jingrow.utils.sleep;

					jingrow.dom.freeze(__("Creating {0}", [pg.pagetype]) + "...");
					// to avoid abrupt UX
					// wait for activity feedback
					sleep(500).then(() => {
						let res = jingrow.model.with_pagetype(pg.pagetype, () => {
							let newdoc = jingrow.model.copy_pg(pg);
							newdoc.__newname = pg.name;
							delete pg.name;
							newdoc.idx = null;
							newdoc.__run_link_triggers = false;
							jingrow.set_route("Form", newdoc.pagetype, newdoc.name);
							jingrow.dom.unfreeze();
						});
						res && res.fail?.(jingrow.dom.unfreeze);
					});
				}
			} catch (e) {
				//
			}
		});
	}

	/// Setup event listeners for events across browser tabs / web workers.
	setup_broadcast_listeners() {
		// booted in another tab -> refresh csrf to avoid invalid requests.
		jingrow.broadcast.on("boot", ({ csrf_token, user }) => {
			if (user && user != jingrow.session.user) {
				jingrow.msgprint({
					message: __(
						"You've logged in as another user from another tab. Refresh this page to continue using system."
					),
					title: __("User Changed"),
					primary_action: {
						label: __("Refresh"),
						action: () => {
							window.location.reload();
						},
					},
				});
				return;
			}

			if (csrf_token) {
				// If user re-logged in then their other tabs won't be usable without this update.
				jingrow.csrf_token = csrf_token;
			}
		});
	}

	setup_moment() {
		moment.updateLocale("en", {
			week: {
				dow: jingrow.datetime.get_first_day_of_the_week_index(),
			},
		});
		moment.locale("en");
		moment.user_utc_offset = moment().utcOffset();
		if (jingrow.boot.timezone_info) {
			moment.tz.add(jingrow.boot.timezone_info);
		}
	}
};

jingrow.get_module = function (m, default_module) {
	var module = jingrow.modules[m] || default_module;
	if (!module) {
		return;
	}

	if (module._setup) {
		return module;
	}

	if (!module.label) {
		module.label = m;
	}

	if (!module._label) {
		module._label = __(module.label);
	}

	module._setup = true;

	return module;
};
