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

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

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

$(document).ready(function () {
    if (!xhiveframework.utils.supportsES6) {
        xhiveframework.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."
            ),
        });
    }
    xhiveframework.start_app();
});

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

    startup() {
        xhiveframework.socketio.init();
        xhiveframework.model.init();

        if (xhiveframework.boot.status === "failed") {
            xhiveframework.msgprint({
                message: xhiveframework.boot.error,
                title: __("Session Start Failed"),
                indicator: "red",
            });
            throw "boot failed";
        }

        this.setup_xhiveframework_vue();
        this.load_bootinfo();
        this.load_user_permissions();
        this.make_nav_bar();
        this.set_favicon();
        this.setup_analytics();
        this.set_fullwidth_if_enabled();
        this.add_browser_class();
        this.setup_energy_point_listeners();
        this.setup_copy_doc_listener();
        this.set_rtl();

        xhiveframework.ui.keys.setup();

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

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

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

        xhiveframework.ui.set_theme();

        // page container
        this.make_page_container();
        this.set_route();

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

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

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

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

        if (!xhiveframework.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 (xhiveframework.ui.startup_setup_dialog && !xhiveframework.boot.setup_complete) {
            xhiveframework.ui.startup_setup_dialog.pre_show();
            xhiveframework.ui.startup_setup_dialog.show();
        }

        xhiveframework.realtime.on("version-update", function () {
            var dialog = xhiveframework.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 (xhiveframework.sys_defaults.email_user_password) {
            var email_list = xhiveframework.sys_defaults.email_user_password.split(",");
            for (var u in email_list) {
                if (email_list[u] === xhiveframework.user.name) {
                    this.set_password(email_list[u]);
                }
            }
        }

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

        if (!xhiveframework.boot.developer_mode) {
            if (xhiveframework.user.has_role("System Manager")) {
                setInterval(function () {
                    xhiveframework.call({
                        method: "xhiveframework.core.doctype.log_settings.log_settings.has_unseen_error_log",
                        args: {
                            user: xhiveframework.session.user,
                        },
                        callback: function (r) {
                            if (r.message.show_alert) {
                                xhiveframework.show_alert({
                                    indicator: "red",
                                    message: r.message.message,
                                });
                            }
                        },
                    });
                }, 600000); // check every 10 minutes
            }
        }
    }

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

    setup_xhiveframework_vue() {
        Vue.prototype.__ = window.__;
        Vue.prototype.xhiveframework = window.xhiveframework;
    }

    set_password(user) {
        var me = this;
        xhiveframework.call({
            method: "xhiveframework.core.doctype.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 xhiveframework.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 xhiveframework.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();
            xhiveframework.call({
                method: "xhiveframework.email.doctype.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"]) {
                        xhiveframework.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 (xhiveframework.boot) {
            this.setup_workspaces();
            xhiveframework.model.sync(xhiveframework.boot.docs);
            this.check_metadata_cache_status();
            this.set_globals();
            this.sync_pages();
            xhiveframework.router.setup();
            this.setup_moment();
            if (xhiveframework.boot.print_css) {
                xhiveframework.dom.set_style(xhiveframework.boot.print_css, "print-style");
            }
            xhiveframework.user.name = xhiveframework.boot.user.name;
            xhiveframework.router.setup();
        } else {
            this.set_as_guest();
        }
    }

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

    load_user_permissions() {
        xhiveframework.defaults.update_user_permissions();

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

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

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

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

        xhiveframework.ui.py_date_format = xhiveframework.boot.sysdefaults.date_format
            .replace("dd", "%d")
            .replace("mm", "%m")
            .replace("yyyy", "%Y");
        xhiveframework.boot.user.last_selected_values = {};
    }

    sync_pages() {
        // clear cached pages if timestamp is not found
        if (localStorage["page_info"]) {
            xhiveframework.boot.allowed_pages = [];
            var page_info = JSON.parse(localStorage["page_info"]);
            $.each(xhiveframework.boot.page_info, function (name, p) {
                if (!page_info[name] || page_info[name].modified != p.modified) {
                    delete localStorage["_page:" + name];
                }
                xhiveframework.boot.allowed_pages.push(name);
            });
        } else {
            xhiveframework.boot.allowed_pages = Object.keys(xhiveframework.boot.page_info);
        }
        localStorage["page_info"] = JSON.stringify(xhiveframework.boot.page_info);
    }

    set_as_guest() {
        xhiveframework.session.user = "Guest";
        xhiveframework.session.user_email = "";
        xhiveframework.session.user_fullname = "Guest";

        xhiveframework.user_defaults = {};
        xhiveframework.user_roles = ["Guest"];
        xhiveframework.sys_defaults = {};
    }

    make_page_container() {
        if ($("#body").length) {
            $(".splash").remove();
            xhiveframework.temp_container = $("<div id='temp-container' style='display: none;'>").appendTo(
                "body"
            );
            xhiveframework.container = new xhiveframework.views.Container();
        }
    }

    make_nav_bar() {
        // toolbar
        if (xhiveframework.boot && xhiveframework.boot.home_page !== "setup-wizard") {
            xhiveframework.xhiveframework_toolbar = new xhiveframework.ui.toolbar.Toolbar();
        }
    }

    logout() {
        var me = this;
        me.logged_out = true;
        return xhiveframework.call({
            method: "logout",
            callback: function (r) {
                if (r.exc) {
                    return;
                }
                me.redirect_to_login();
            },
        });
    }

    handle_session_expired() {
        if (!xhiveframework.app.session_expired_dialog) {
            var dialog = new xhiveframework.ui.Dialog({
                title: __("Session Expired"),
                keep_open: true,
                fields: [
                    {
                        fieldtype: "Password",
                        fieldname: "password",
                        label: __("Please Enter Your Password to Continue"),
                    },
                ],
                onhide: () => {
                    if (!dialog.logged_in) {
                        xhiveframework.app.redirect_to_login();
                    }
                },
            });
            dialog.set_primary_action(__("Login"), () => {
                dialog.set_message(__("Authenticating..."));
                xhiveframework.call({
                    method: "login",
                    args: {
                        usr: xhiveframework.session.user,
                        pwd: dialog.get_values().password,
                    },
                    callback: (r) => {
                        if (r.message === "Logged In") {
                            dialog.logged_in = true;

                            // revert backdrop
                            $(".modal-backdrop").css({
                                opacity: "",
                                "background-color": "#334143",
                            });
                        }
                        dialog.hide();
                    },
                    statusCode: () => {
                        dialog.hide();
                    },
                });
            });
            xhiveframework.app.session_expired_dialog = dialog;
        }
        if (!xhiveframework.app.session_expired_dialog.display) {
            xhiveframework.app.session_expired_dialog.show();
            // add backdrop
            $(".modal-backdrop").css({
                opacity: 1,
                "background-color": "#4B4C9D",
            });
        }
    }

    redirect_to_login() {
        window.location.href = "/";
    }

    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) {
                // 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 (xhiveframework.container.page.save_action) {
                xhiveframework.container.page.save_action();
            }
        }, 100);
    }

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

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

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

        // Iterate over changelog
        var change_log_dialog = xhiveframework.msgprint({
            message: xhiveframework.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 () {
            xhiveframework.call({
                method: "xhiveframework.utils.change_log.update_last_known_versions",
            });
            me.show_notes();
        };
    }

    show_update_available() {
        if (xhiveframework.boot.sysdefaults.disable_system_update_notification) return;

        xhiveframework.call({
            method: "xhiveframework.utils.change_log.show_update_popup",
        });
    }

    setup_analytics() {
        if (window.mixpanel) {
            window.mixpanel.identify(xhiveframework.session.user);
            window.mixpanel.people.set({
                $first_name: xhiveframework.boot.user.first_name,
                $last_name: xhiveframework.boot.user.last_name,
                $created: xhiveframework.boot.user.creation,
                $email: xhiveframework.session.user,
            });
        }
    }

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

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

    set_rtl() {
        if (xhiveframework.utils.is_rtl()) {
            $('body').addClass('xhiveframework-rtl');
        }
    }

    show_notes() {
        var me = this;
        if (xhiveframework.boot.notes.length) {
            xhiveframework.boot.notes.forEach(function (note) {
                if (!note.seen || note.notify_on_every_login) {
                    var d = xhiveframework.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) {
                            xhiveframework.call({
                                method: "xhiveframework.desk.doctype.note.note.mark_as_seen",
                                args: {
                                    note: note.name,
                                },
                            });
                        }

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

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

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

    setup_copy_doc_listener() {
        $("body").on("paste", (e) => {
            try {
                let pasted_data = xhiveframework.utils.get_clipboard_data(e);
                let doc = JSON.parse(pasted_data);
                if (doc.doctype) {
                    e.preventDefault();
                    const sleep = xhiveframework.utils.sleep;

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

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

xhiveframework.get_module = function (m, default_module) {
    var module = xhiveframework.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;
};

