
/*
 * ==========================================================
 * ADMINISTRATION SCRIPT
 * ==========================================================
 *
 * Main Javascript admin file. © 2017-2026 board.support. All rights reserved.
 * 
 */

'use strict';

(function ($) {

    // Global
    var admin;
    var header;

    // Conversation  
    var conversations = [];
    var conversation_area;
    var conversations_area;
    var conversations_area_list;
    var conversations_user_details;
    var conversations_admin_list;
    var conversations_admin_list_ul;
    var conversations_filters;
    var saved_replies = false;
    var saved_replies_list = false;
    var woocommerce_products_box = false;
    var woocommerce_products_box_ul = false;
    var pagination = 1;
    var notes_panel;
    var tags_panel;
    var attachments_panel;
    var direct_message_box;
    var chatbot_training_panel;
    var suggestions_area;
    var pagination_count = 1;
    var open_ai_button_rewrite;
    var editor_textarea;

    // Users
    var users_area;
    var users_table;
    var users_table_menu;
    var users_filters;
    var users = {};
    var users_pagination = 1;
    var users_pagination_count = 1;
    var profile_box;
    var profile_edit_box;
    var away_mode = true;

    // Settings
    var settings_area;
    var automations_area;
    var automations_area_select;
    var automations_area_nav;
    var conditions_area;
    var custom_selects = {};

    // Articles
    var articles_area;
    var articles_content;
    var articles_content_categories;
    var articles_category_select;
    var articles_category_parent_select;
    var articles_save_required = false;
    var articles_save_required_stop = true;

    // Chatbot
    var chatbot_area;
    var chatbot_files_table;
    var chatbot_website_table;
    var chatbot_qea_repeater;
    var chatbot_playground_editor;
    var chatbot_playground_history_panel;
    var chatbot_playground_area;
    var flows_nav;
    var flows_area;
    var flow_scroll_interval;
    var is_over_connector = false;
    var conversations_qea = [];
    var step_scroll_positions = [];

    // Miscellaneus
    var upload_input;
    var upload_target;
    var upload_function;
    var upload_on_success;
    var language_switcher_target;
    var timeout;
    var alertOnConfirmation;
    var alertOnCancel;
    var responsive = $(window).width() < 465;
    var scrolls = { last: 0, header: true, always_hidden: false };
    var localhost = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
    var today = new Date();
    var is_busy = false;
    var agent_online = true;
    var active_interval = false;
    var pusher_timeout;
    var away_timeout;
    var temp;
    var overlay;
    var SITE_URL;
    var ND = 'undefined';
    var wp_admin = false;
    var touchmove;
    var touchmove_x;
    var touchmove_y;
    var editor_js = false;
    var editor_js_loading = false;
    var active_keydown;
    var reports_area;
    var select_departments;
    var active_admin_area = 'conversations';

    /*
    * ----------------------------------------------------------
    * External plugins
    * ----------------------------------------------------------
    */

    // miniTip 1.5.3 | (c) 2011, James Simpson | Dual licensed under the MIT and GPL
    $.fn.miniTip = function (t) { var e = $.extend({ title: "", content: !1, delay: 300, anchor: "n", event: "hover", fadeIn: 200, fadeOut: 200, aHide: !0, maxW: "250px", offset: 5, stemOff: 0, doHide: !1, className: "" }, t); admin && 0 == admin.find("#miniTip").length && admin.append('<div id="miniTip" class="sb-tooltip"><div></div></div>'); var n = admin.find("#miniTip"), a = n.find("div"); return e.doHide ? (n.stop(!0, !0).fadeOut(e.fadeOut), !1) : this.each(function () { var t = $(this), o = e.content ? e.content : t.attr("title"); if ("" != o && void 0 !== o) { window.delay = !1; var i = !1, r = !0; e.content || t.removeAttr("title"), "hover" == e.event ? (t.hover(function () { n.removeAttr("click"), r = !0, s.call(this) }, function () { r = !1, d() }), e.aHide || n.hover(function () { i = !0 }, function () { i = !1, setTimeout(function () { !r && !n.attr("click") && d() }, 20) })) : "click" == e.event && (e.aHide = !0, t.click(function () { return n.attr("click", "t"), n.data("last_target") !== t ? s.call(this) : "none" == n.css("display") ? s.call(this) : d(), n.data("last_target", t), $("html").unbind("click").click(function (t) { "block" == n.css("display") && !$(t.target).closest("#miniTip").length && ($("html").unbind("click"), d()) }), !1 })); var s = function () { e.show && e.show.call(this, e), e.content && "" != e.content && (o = e.content), a.html(o), e.render && e.render(n), n.hide().width("").width(n.width()).css("max-width", e.maxW); var i = t.is("area"); if (i) { var r, s = [], d = [], c = t.attr("coords").split(","); function h(t, e) { return t - e } for (r = 0; r < c.length; r++)s.push(c[r++]), d.push(c[r]); var f = t.parent().attr("name"), l = $("img[usemap=\\#" + f + "]").offset(), p = parseInt(l.left, 10) + parseInt((parseInt(s.sort(h)[0], 10) + parseInt(s.sort(h)[s.length - 1], 10)) / 2, 10), u = parseInt(l.top, 10) + parseInt((parseInt(d.sort(h)[0], 10) + parseInt(d.sort(h)[d.length - 1], 10)) / 2, 10) } else u = parseInt(t.offset().top, 10), p = parseInt(t.offset().left, 10); var m = i ? 0 : parseInt(t.outerWidth(), 10), I = i ? 0 : parseInt(t.outerHeight(), 10), v = n.outerWidth(), w = n.outerHeight(), g = Math.round(p + Math.round((m - v) / 2)), T = Math.round(u + I + e.offset + 8), b = Math.round(v - 16) / 2 - parseInt(n.css("borderLeftWidth"), 10), y = 0, H = p + m + v + e.offset + 8 > parseInt($(window).width(), 10), W = v + e.offset + 8 > p, k = w + e.offset + 8 > u - $(window).scrollTop(), M = u + I + w + e.offset + 8 > parseInt($(window).height() + $(window).scrollTop(), 10), x = e.anchor; W || "e" == e.anchor && !H ? "w" != e.anchor && "e" != e.anchor || (x = "e", y = Math.round(w / 2 - 8 - parseInt(n.css("borderRightWidth"), 10)), b = -8 - parseInt(n.css("borderRightWidth"), 10), g = p + m + e.offset + 8, T = Math.round(u + I / 2 - w / 2)) : (H || "w" == e.anchor && !W) && ("w" != e.anchor && "e" != e.anchor || (x = "w", y = Math.round(w / 2 - 8 - parseInt(n.css("borderLeftWidth"), 10)), b = v - parseInt(n.css("borderLeftWidth"), 10), g = p - v - e.offset - 8, T = Math.round(u + I / 2 - w / 2))), M || "n" == e.anchor && !k ? "n" != e.anchor && "s" != e.anchor || (x = "n", y = w - parseInt(n.css("borderTopWidth"), 10), T = u - (w + e.offset + 8)) : (k || "s" == e.anchor && !M) && ("n" != e.anchor && "s" != e.anchor || (x = "s", y = -8 - parseInt(n.css("borderBottomWidth"), 10), T = u + I + e.offset + 8)), "n" == e.anchor || "s" == e.anchor ? v / 2 > p ? (g = g < 0 ? b + g : b, b = 0) : p + v / 2 > parseInt($(window).width(), 10) && (g -= b, b *= 2) : k ? (T += y, y = 0) : M && (T -= y, y *= 2), delay && clearTimeout(delay), delay = setTimeout(function () { n.css({ "margin-left": g + "px", "margin-top": T + "px" }).stop(!0, !0).fadeIn(e.fadeIn) }, e.delay), n.attr("class", "sb-tooltip " + x + (e.className ? " " + e.className : "")) }, d = function () { (!e.aHide && !i || e.aHide) && (delay && clearTimeout(delay), delay = setTimeout(function () { c() }, e.delay)) }, c = function () { !e.aHide && !i || e.aHide ? (n.stop(!0, !0).fadeOut(e.fadeOut), e.hide && e.hide.call(this)) : setTimeout(function () { d() }, 200) } } }) };

    /*
    * ----------------------------------------------------------
    * Functions
    * ----------------------------------------------------------
    */

    $.fn.sbLanguageSwitcher = function (langs = [], source = '', active_language = false) {
        let code = `<div class="sb-language-switcher" data-source="${source}">`;
        let added = [];
        let element = $(this).hasClass('sb-language-switcher-cnt') ? $(this) : $(this).find('.sb-language-switcher-cnt');
        for (var i = 0; i < langs.length; i++) {
            let language = isString(langs[i]) ? langs[i] : langs[i][0];
            let id = isString(langs[i]) || !langs[i][1] ? false : langs[i][1];
            if (added.includes(language)) {
                continue;
            }
            code += `<span ${active_language == language ? 'class="sb-active" ' : ''}data-language="${language}"${id ? ' data-id="' + id + '"' : ''}><i class="sb-icon-close"></i><img src="${SB_URL}/media/flags/${language.toLowerCase()}.png" /></span>`;
            added.push(language);
        }
        element.find('.sb-language-switcher').remove();
        element.append(code + `<i data-sb-tooltip="${sb_('Add translation')}" class="sb-icon-plus"></i></div>`);
        element.sbInitTooltips();
        return this;
    }

    $.fn.sbShowLightbox = function (popup = false, action = '') {
        admin.find('.sb-lightbox').sbActive(false);
        overlay.sbActive(true);
        $(this).sbActive(true);
        if (popup) {
            $(this).addClass('sb-popup-lightbox').attr('data-action', action);
        } else {
            $(this).css({ 'margin-top': ($(this).outerHeight() / -2) + 'px', 'margin-left': ($(this).outerWidth() / -2) + 'px' })
        }
        $('body').addClass('sb-lightbox-active');
        setTimeout(() => { SBAdmin.open_popup = this }, 500);
        this.preventDefault;
        return this;
    }

    $.fn.sbHideLightbox = function () {
        $(this).find('.sb-lightbox,.sb-popup-lightbox').sbActive(false).removeClass('sb-popup-lightbox').removeAttr('data-action');
        overlay.sbActive(false);
        $('body').removeClass('sb-lightbox-active');
        SBAdmin.open_popup = false;
        return this;
    }

    $.fn.sbInitTooltips = function () {
        $(this).find('[data-sb-tooltip]').each(function () {
            let text = $(this).attr('data-sb-tooltip');
            $(this).miniTip({
                content: text,
                anchor: 's',
                delay: 500,
                className: text.length > 40 ? 'sb-tooltip-large' : ''
            });
        });
        return this;
    }

    function infoBottom(text, type = false) {
        return SBAdmin.infoBottom(text, type);
    }

    function infoPanel(text, type = 'info', onConfirm = false, id = '', title = '', scroll = false, skip = false, onCancel = false) {
        return SBAdmin.infoPanel(text, type, onConfirm, id, title, scroll, skip, onCancel);
    }

    function activeUser(value) {
        return SBAdmin.activeUser(value);
    }

    function loading(element) {
        return SBAdmin.loading(element);
    }

    function loadingGlobal(show = true, is_overlay = true) {
        return SBAdmin.loadingGlobal(show, is_overlay);
    }

    function sb_(text) {
        return SB_TRANSLATIONS && text in SB_TRANSLATIONS ? SB_TRANSLATIONS[text] : text;
    }

    function isPWA() {
        return (window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone) || document.referrer.includes('android-app://');
    }

    function clearCache() {
        if (typeof caches !== ND) caches.delete('sb-pwa-cache');
    }

    function collapse(target, max_height) {
        SBAdmin.collapse(target, max_height);
    }

    function searchInput(input, searchFunction) {
        let icon = $(input).parent().find('i');
        let search = $(input).val();
        SBF.search(search, () => {
            icon.sbLoading(true);
            searchFunction(search, icon);
        });
    }

    function scrollPagination(area, check = false, offset = 0) {
        if (check) return $(area).scrollTop() + $(area).innerHeight() >= ($(area)[0].scrollHeight - 1);
        $(area).scrollTop($(area)[0].scrollHeight - offset);
    }

    function editorJSLoad(data = false) {
        if (editor_js_loading) return;
        if (editor_js === false) {
            editor_js = true;
            $.getScript(SB_URL + '/vendor/editorjs.js', () => {
                editorJSLoad(data);
            });
            return;
        }
        editorJSDestroy();
        editor_js_loading = true;
        editor_js = new EditorJS({
            data: isString(data) ? { time: Date.now(), blocks: [data ? { id: 'sb', type: 'raw', data: { html: data } } : { id: 'sb', type: 'paragraph', data: { text: '' } }] } : data,
            i18n: {
                messages: {
                    ui: {
                        blockTunes: {
                            toggler: {
                                'Click to tune': sb_('Click to tune')
                            },
                        },
                        inlineToolbar: {
                            converter: {
                                'Convert to': sb_('Convert to')
                            }
                        },
                        toolbar: {
                            toolbox: {
                                'Add': sb_('Add')
                            }
                        }
                    },
                    toolNames: {
                        Text: sb_('Text'),
                        Heading: sb_('Heading'),
                        List: sb_('List'),
                        Image: sb_('Image'),
                        Code: sb_('Code'),
                        'Raw HTML': sb_('Raw HTML'),
                        Bold: sb_('Bold'),
                        Italic: sb_('Italic'),
                        Link: sb_('Link'),
                    },
                    tools: {
                        list: {
                            Ordered: sb_('Ordered'),
                            Unordered: sb_('Unordered')
                        }
                    },
                    blockTunes: {
                        delete: {
                            Delete: sb_('Delete')
                        },
                        moveUp: {
                            'Move up': sb_('Move up')
                        },
                        moveDown: {
                            'Move down': sb_('Move down')
                        }
                    },
                },
                direction: admin.hasClass('sb-rtl') ? 'rtl' : 'ltr'
            },
            tools: {
                list: {
                    class: List,
                    inlineToolbar: true
                },
                image: {
                    class: ImageTool,
                    config: {
                        uploader: {
                            uploadByFile(file) {
                                let form = new FormData();
                                form.append('file', file);
                                return new Promise((resolve) => {
                                    $.ajax({
                                        url: SB_URL + '/include/upload.php',
                                        cache: false,
                                        contentType: false,
                                        processData: false,
                                        data: form,
                                        type: 'POST',
                                        success: function (response) {
                                            response = JSON.parse(response);
                                            if (response[0] == 'success') {
                                                resolve({
                                                    success: 1,
                                                    file: {
                                                        url: response[1],
                                                    }
                                                })
                                            } else console.log(response);
                                        }
                                    })
                                })
                            }
                        }
                    }
                },
                divider: class {
                    static get toolbox() {
                        return {
                            title: 'Divider',
                            icon: '<svg width="14" height="14" xmlns="http://www.w3.org/2000/svg"><path d="M2 7h10v1H2z" /></svg>'
                        };
                    }

                    render() {
                        const hr = document.createElement('hr');
                        hr.classList.add('ce-divider');
                        return hr;
                    }

                    save() {
                        return;
                    }
                },
                info: class {
                    static get toolbox() {
                        return {
                            title: 'Info',
                            icon: '<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="4" width="12" height="8" rx="2" ry="2" stroke="currentColor" fill="none" stroke-width="1.5"/></svg>'
                        };
                    }
                    static get tunes() {
                        return [
                            { name: 'ce-yellow' },
                            { name: 'ce-green' },
                            { name: 'ce-red' },
                            { name: 'ce-brown' },
                            { name: 'ce-blue' },
                            { name: 'ce-gray' }
                        ];
                    }

                    static get enableLineBreaks() {
                        return true;
                    }

                    render() {
                        this.wrapper = document.createElement('div');
                        this.wrapper.classList.add('ce-info-block');
                        const input = document.createElement('div');
                        input.classList.add('editor-box-input');
                        input.contentEditable = true;
                        input.innerHTML = this.data && this.data.text ? this.data.text : '';
                        this.wrapper.classList.add(this.data.color ? this.data.color : 'ce-yellow');
                        this.wrapper.appendChild(input);
                        this.input = input;
                        return this.wrapper;
                    }

                    save(block) {
                        return { text: block.querySelector('.editor-box-input').innerHTML.trim(), color: this.color };
                    }

                    renderSettings() {
                        const wrapper = document.createElement('div');
                        ['ce-yellow', 'ce-green', 'ce-black', 'ce-blue', 'ce-red', 'ce-gray'].forEach(color => {
                            const btn = document.createElement('button');
                            btn.type = 'button';
                            btn.classList.add('cdx-settings-button');
                            if (color === this.color) {
                                btn.classList.add('cdx-settings-button--active');
                            }
                            btn.innerHTML = `<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="12" height="12" rx="3" ry="3" fill="${({ 'ce-yellow': '#fcde66', 'ce-green': '#90c66f', 'ce-red': '#c44837', 'ce-black': '#6e6e6e', 'ce-gray': '#a9a9a9', 'ce-blue': '#8ab2d6' })[color]}" /></svg>`;
                            btn.addEventListener('click', () => {
                                this.color = color;
                                this.wrapper.classList.remove('ce-yellow', 'ce-green', 'ce-red', 'ce-gray', 'ce-black', 'ce-blue');
                                this.wrapper.classList.add(this.color);
                                Array.from(wrapper.children).forEach(c => c.classList.remove('cdx-settings-button--active'));
                                btn.classList.add('cdx-settings-button--active');
                            });
                            wrapper.appendChild(btn);
                        });
                        return wrapper;
                    }

                    constructor({ data }) {
                        this.data = data || {};
                        this.color = this.data.color || 'ce-yellow';

                    }
                },
                header: Header,
                code: CodeTool,
                raw: RawTool
            },
            onReady: () => {
                editor_js_loading = false;
                articles_save_required_stop = true;
                articles_save_required = false;
            },
            onChange: () => {
                if (articles_save_required_stop) {
                    articles_save_required_stop = false;
                } else {
                    articles_save_required = true;
                }
            },
            minHeight: 50
        });
    }

    function editorJSHTML(blocks) {
        let code = '';
        blocks.map(block => {
            switch (block.type) {
                case 'header':
                    code += `<h${block.data.level}>${block.data.text}</h${block.data.level}>`;
                    break;
                case 'paragraph':
                    code += `<p>${block.data.text}</p>`;
                    break;
                case 'image':
                    code += `<img class="img-fluid" src="${block.data.file.url}" title="${block.data.caption}" /><em>${block.data.caption}</em>`;
                    break;
                case 'list':
                    code += '<ul class="sb-ul-' + block.data.style + '">';
                    block.data.items.forEach(function (li) {
                        code += `<li>${li.content}</li>`;
                    });
                    code += '</ul>';
                    break;
                case 'code':
                    code += `<code>${block.data.code}</code>`;
                    break;
                case 'raw':
                    code += `<div class="sb-raw-html">${block.data.html}</div>`;
                    break;
                case 'divider':
                    code += `<hr class="sb-divider" />`;
                    break;
                case 'info':
                    code += `<p class="sb-info-box ${block.data.color}">${block.data.text}</p>`;
                    break;
            }
        });
        return code;
    }

    function editorJSDestroy() {
        if (typeof editor_js.destroy !== ND) {
            editor_js.destroy();
            editor_js = false;
        }
    }

    function isString(object) {
        return typeof object === 'string';
    }

    function pushState(url_parameters) {
        if (wp_admin) return;
        window.history.pushState('', '', url_parameters);
    }

    function cloudURL() {
        return SB_ADMIN_SETTINGS.cloud ? ('&cloud=' + SB_ADMIN_SETTINGS.cloud.token) : '';
    }

    function urlStrip(url) {
        return url.replace('https://', '').replace('http://', '').replace('www.', '').replace(/\/$/, '');
    }

    function saved_reply_search(search) {
        SBF.search(search, () => {
            let code = '';
            let all = search.length > 1 ? false : true;
            let area = saved_replies.find('.sb-replies-list > ul');
            let no_results = `<li class="sb-no-results">${sb_('No results found.')}</li>`;
            for (var i = 0; i < saved_replies_list.length; i++) {
                let name = saved_replies_list[i]['reply-name'];
                if (all || name.toLowerCase().includes(search) || name.replaceAll('-', ' ').toLowerCase().includes(search) || saved_replies_list[i]['reply-text'].toLowerCase().includes(search)) {
                    code += `<li><div>${name}</div><div>${saved_replies_list[i]['reply-text']}</div></li>`;
                }
            }
            area.html(code);
            if (!all && SB_ADMIN_SETTINGS.chatbot_features) {
                let icon = area.closest('.sb-popup').find('.sb-icon-search');
                icon.sbLoading(true);
                SBF.ajax({
                    function: 'open-ai-message',
                    model: SB_ADMIN_SETTINGS.open_ai_model,
                    message: search
                }, (response) => {
                    area.html(response[1] && (!response[5] || !response[5].unknow_answer) ? `${code}<li><div></div><div>${response[1]}</div></li>` : (code ? code : no_results));
                    icon.sbLoading(false);
                });
            } else if (!code) {
                area.html(no_results);
            }
        });
    }

    function whatsapp_direct_message_box(user_ids) {
        let box = admin.find('#sb-whatsapp-send-template-box');
        loadingGlobal();
        SBF.ajax({
            function: 'whatsapp-get-templates'
        }, (response) => {
            let code = '<option value=""></option>';
            let provider = response[0];
            let twilio = provider == 'twilio';
            response = response[1];
            if (response.error) {
                return infoBottom(response.error.message, 'error');
            }
            if (!Array.isArray(response)) {
                return infoBottom(response, 'error');
            }
            for (var i = 0; i < response.length; i++) {
                if (provider == 'official' && response[i].status == 'APPROVED' && (!SB_ACTIVE_AGENT.department || !response[i].department.length || response[i].department.includes(SB_ACTIVE_AGENT.department))) {
                    code += `<option value="${response[i].name}" data-languages="${response[i].languages}" data-phone-id="${response[i].phone_number_id}">${response[i].name} (${response[i].label})</option>`;
                }
                if (twilio) {
                    code += `<option value="${response[i].sid}">${response[i].friendly_name}</option>`;
                }
            }
            box.attr('data-provider', provider);
            box.find('#sb-whatsapp-send-template-list').html(code);
            SBForm.clear(box);
            box.find('.sb-direct-message-users').val(user_ids.length ? user_ids.join(',') : 'all');
            box.find('.sb-bottom > div').html('');
            box.find('.sb-loading').sbLoading(false);
            loadingGlobal(false);
            box.sbShowLightbox();
        });
    }

    function dialogDeleteFile(url, id, title) {
        window.open(url);
        infoPanel(`<span>${sb_('For security reasons, delete the file after downloading it. Close this window to automatically delete it. File location:')}</span><pre>${url}</pre>`, 'info', false, id, title);
    }

    function touchEndEvent() {
        touchmove_x = false;
        touchmove_y = false;
        setTimeout(() => {
            if (touchmove) {
                touchmove[1].css('transform', '');
                touchmove[1].removeClass('sb-touchmove');
            }
        }, 100);
    }

    function getListConversation(conversation_id) {
        return conversations_admin_list_ul.find(`[data-conversation-id="${conversation_id}"]`);
    }

    /*
    * ----------------------------------------------------------
    * Apps
    * ----------------------------------------------------------
    */

    var SBApps = {

        dialogflow: {
            smart_reply_busy: false,

            smartReply: function (message = false) {
                let conversation_id = SBChat.conversation.id;
                if (this.smart_reply_busy == conversation_id) {
                    return;
                }
                this.smart_reply_busy = conversation_id;
                SBF.ajax({
                    function: 'open-ai-smart-reply',
                    message: message,
                    conversation_id: conversation_id
                }, (response) => {
                    this.smart_reply_busy = false;
                    if (SBChat.conversation.id && conversation_id === SBChat.conversation.id) {
                        let suggestions = response.suggestions;
                        let code = '';
                        let is_bottom = Math.abs(conversations_area_list[0].scrollTop - (conversations_area_list[0].scrollHeight - conversations_area_list[0].offsetHeight)) <= 1;
                        let last_conversation_message = SBChat.conversation && SBChat.conversation.getLastMessage() ? SBChat.conversation.getLastMessage().message : false;
                        for (var i = 0; i < suggestions.length; i++) {
                            if (suggestions[i] != last_conversation_message) {
                                code += `<span>${SBF.escape(suggestions[i])}</span>`;
                            }
                        }
                        suggestions_area.html(code);
                        if (is_bottom) {
                            SBChat.scrollBottom();
                        }
                    }
                });
            },

            trainingPanel: {
                qea: [],
                original_response: false,

                show: function (message_id) {
                    let question = '';
                    let message = SBChat.conversation.getMessage(message_id);
                    let response = message.message;
                    if (SBF.isAgent(message.get('user_type'))) {
                        question = SBChat.conversation.getLastUserMessage(message.get('index'));
                        if (question && question.payload('sb-human-takeover')) {
                            question = SBChat.conversation.getLastUserMessage(question.get('index')).message;
                        } else {
                            question = question.message;
                        }
                    } else {
                        question = response;
                        let agent_message = SBChat.conversation.getNextMessage(message.id, 'agent');
                        if (agent_message) {
                            response = agent_message.message;
                        }
                    }
                    SBF.ajax({
                        function: 'open-ai-get-qea-training'
                    }, (response) => {
                        let code = '<option value="">' + sb_('New Q&A') + '</option>';
                        for (var i = 0; i < response.length; i++) {
                            this.qea = response;
                            code += `<option value="${i}">${response[i][0][0]}</option>`;
                        }
                        chatbot_training_panel.find('#sb-qea-select').html(code);
                    });
                    SBApps.openAI.generateQuestions(question);
                    chatbot_training_panel.attr('data-message-id', message.id);
                    chatbot_training_panel.find('.sb-type-text:not(.sb-first)').remove();
                    chatbot_training_panel.find('.sb-type-text input').val(question);
                    chatbot_training_panel.find('#sb-qea-select').val('');
                    chatbot_training_panel.find('.sb-search-btn').sbActive(false).find('input').val('');
                    this.search('');
                    this.original_response = response;
                    chatbot_training_panel.find('textarea').val(response);
                    chatbot_training_panel.sbShowLightbox();
                },

                submit: function (button) {
                    if (loading(button)) return;
                    let questions = [];
                    let answer = chatbot_training_panel.find('textarea').val();
                    let existing_qea = chatbot_training_panel.find('#sb-qea-select').val();
                    chatbot_training_panel.find('.sb-type-text input').each(function () {
                        if ($(this).val()) {
                            questions.push($(this).val());
                        }
                    });
                    if ((!answer && !existing_qea) || questions.length == 0) {
                        SBForm.showErrorMessage(chatbot_training_panel, 'Enter an answer and at least one question.');
                        $(button).sbLoading(false);
                    } else {
                        let questions_answers;
                        if (existing_qea) {
                            this.qea[existing_qea][0] = this.qea[existing_qea][0].concat(questions);
                            questions_answers = this.qea[existing_qea];
                        } else {
                            questions_answers = [[questions, answer]];
                        }
                        SBF.ajax({
                            function: 'open-ai-qea-training',
                            questions_answers: questions_answers,
                            conversation_id: SBChat.conversation.id,
                            update_index: existing_qea,
                            language: chatbot_training_panel.find('#sb-chatbot-training-panel-language select').val()
                        }, (response) => {
                            $(button).sbLoading(false);
                            if (response === true) {
                                admin.sbHideLightbox();
                                infoBottom('Training completed');
                            } else {
                                SBForm.showErrorMessage(chatbot_training_panel, response.error && response.error.message ? response.error && response.error.message : 'Error');
                            }
                        });
                    }
                },

                search: function (search) {
                    let all = search.length > 1 ? false : true;
                    let code = all ? `<option value="">${sb_('New Q&A')}</option>` : '';
                    search = search.toLowerCase();
                    for (var i = 0; i < this.qea.length; i++) {
                        if (all || (this.qea[i][0].join('').toLowerCase().includes(search) || this.qea[i][1].toLowerCase().includes(search))) {
                            code += `<option value="${i}">${this.qea[i][0][0]}</option>`;
                        }
                    }
                    chatbot_training_panel.find('#sb-qea-select').html(code).change();
                    if (all) {
                        chatbot_training_panel.find('textarea').val(this.original_response);
                    }
                },

                preview: function (index) {
                    if (index) {
                        let code = '';
                        let qea = this.qea[index];
                        if (qea[0].length > 1) {
                            let max = qea[0].length > 15 ? 15 : qea[0].length;
                            for (var i = 0; i < max; i++) {
                                code += `<span>${qea[0][i]}</span>`;
                            }
                            infoPanel(code, 'info', false, 'qea-preview-box', '', max > 10);
                        }
                    }
                }
            },

            translate: function (strings, language_code, onSuccess, message_ids, conversation_id) {
                if (strings.length) {
                    SBF.ajax({
                        function: 'google-translate',
                        strings: strings,
                        language_code: language_code,
                        message_ids: message_ids,
                        conversation_id: conversation_id
                    }, (response) => {
                        if (Array.isArray(response)) {
                            onSuccess(response);
                        } else {
                            SBF.error(JSON.stringify(response), 'SBApps.dialogflow.translate');
                            return false;
                        }
                    });
                }
            }
        },

        openAI: {
            urls_history: [],
            progress: 1,

            rewriteButton: function (value) {
                if (open_ai_button_rewrite.length) {
                    open_ai_button_rewrite.sbActive(value.length > 2 && value.indexOf(' '));
                }
            },

            rewrite: function (message, onSuccess) {
                SBF.ajax({
                    function: 'open-ai-rewrite-message',
                    message: message
                }, (response) => {
                    SBConversations.previous_editor_text = message;
                    onSuccess(response);
                });
            },

            troubleshoot: function () {
                let status = SB_ADMIN_SETTINGS.open_ai_chatbot_status;
                if (status !== true) {
                    infoBottom(status == 'inactive' ? 'Enable the chatbot in Settings > Artificial Intelligence > OpenAI > Chatbot.' : (status == 'key' ? 'Enter the OpenAI API key in Settings > Artificial Intelligence > OpenAI > API key.' : 'The training data is ignored. Change the chatbot mode in Settings > Artificial Intelligence > OpenAI > Chatbot mode.'), 'error');
                }
                return status;
            },

            getCode: {
                set_data: function (data) {
                    let code = '';
                    let code_select_user_details = this.select_user_details();
                    if (!data || !data.length) {
                        data = [['', '']];
                    }
                    for (var i = 0; i < data.length; i++) {
                        code += `<div class="repeater-item"><div>${code_select_user_details.replace(`"${data[i][0]}"`, `"${data[i][0]}" selected`)}<div class="sb-setting"><input type="url" placeholder="${sb_('Enter the value')}" value="${data[i][1]}"></div></div><i class="sb-icon-close"></i></div>`;
                    }
                    return this.repeater_('Data', code);
                },

                actions: function (actions) {
                    let action_list = [['tags', 'Assign tags'], ['department', 'Assign a department'], ['agent', 'Assign an agent'], ['redirect', 'Go to URL'], ['open_article', 'Show an article'], ['transcript', 'Download transcript'], ['transcript_email', 'Email transcript'], ['send_email', 'Send email to user'], ['send_email_agents', 'Send email to agents'], ['archive_conversation', 'Archive the conversation'], ['human_takeover', 'Human takeover']];
                    let code = '';
                    let code_2 = '';
                    if (!actions || !actions.length) {
                        actions = [['tags', '']];
                    }
                    for (var i = 0; i < action_list.length; i++) {
                        code += `<option value="${action_list[i][0]}">${sb_(action_list[i][1])}</option>`;
                    }
                    for (var i = 0; i < actions.length; i++) {
                        code_2 += `<div class="repeater-item"><div><div class="sb-setting"><select>${code.replace(`"${actions[i][0]}"`, `"${actions[i][0]}" selected`)}</select></div>${this.action(actions[i][0], actions[i][1])}</div><i class="sb-icon-close"></i></div>`;
                    }
                    return this.repeater_('Actions', code_2);
                },

                action: function (action, value) {
                    let help = { tags: 'Enter tag names, separated by commas', department: 'Enter the department ID', agent: 'Enter the agent ID', redirect: 'Enter the URL', open_article: 'Enter the article ID', send_email: 'Enter a message', send_email_agents: 'Enter a message' };
                    let input_types = { department: 'number', agent: 'number', redirect: 'url' };
                    return ['send_email_agents', 'send_email', 'open_article', 'redirect', 'agent', 'department', 'tags'].includes(action) ? `<div class="sb-setting"><input type="${input_types[action] ? input_types[action] : 'text'}" value="${value}" placeholder="${sb_(help[action])}" value="${value}"></div>` : '';
                },

                select_user_details: function () {
                    let code = '<div class="sb-setting"><select>';
                    let user_details = [['full_name', 'Name'], ['email', 'Email'], ['password', 'Password']].concat(SBUsers.getExtraDetailsList());
                    for (var i = 0; i < user_details.length; i++) {
                        code += `<option value="${user_details[i][0]}">${sb_(user_details[i][1])}</option>`;
                    }
                    return code + `</select></div>`;
                },

                repeater_: function (title, code) {
                    return `<div class="sb-title">${sb_(title)}</div><div data-type="repeater" class="sb-setting sb-type-repeater"><div class="input"><div class="sb-repeater sb-repeater-block-${SBF.stringToSlug(title)}">${code}</div><div class="sb-btn sb-repeater-add sb-icon"><i class="sb-icon-plus"></i>${sb_('Add new item')}</div></div></div>`;
                }
            },

            generateQuestions: function (expression) {
                if (SB_ADMIN_SETTINGS.open_ai_user_expressions && expression) {
                    let loader = chatbot_training_panel.find('[data-value="add"]');
                    loader.sbLoading(true);
                    chatbot_training_panel.find('.sb-open-ai-intent').remove();
                    SBF.ajax({ function: 'open-ai-user-expressions', message: expression }, (response) => {
                        let code = '';
                        for (var i = 0; i < response.length; i++) {
                            if (response[i]) {
                                code += `<div class="sb-setting sb-type-text sb-open-ai-intent"><input type="text" value="${response[i].replace(/"/g, '')}"></div>`;
                            }
                        }
                        if (code) chatbot_training_panel.find('> div > .sb-type-text').last().after(code);
                        loader.sbLoading(false);
                    });
                }
            },

            getAudioTranscriptCode: function (segments) {
                let code = `<div class="sb-title">${sb_('Transcript')}</div><div class="sb-audio-transcript-cnt">`;
                segments.forEach(segment => {
                    code += `<div data-speaker="${segment.speaker}"><span>${sb_('Speaker')} ${segment.speaker}</span><span>${segment.text}</span></div>`;
                });
                return code + '</div>';
            },

            flows: {
                flows: [],

                set: function (flow) {
                    if (typeof flow == 'string') {
                        flow = flow.trim().replaceAll('"', '').replaceAll('_', '-');
                        if (flow) {
                            flow = { name: flow.replace(/[^a-zA-Z\u00C0-\u1FFF\u2C00-\uD7FF\uAC00-\uD7A3]/g, ''), label: flow, steps: [[[{ type: 'start', start: 'message', message: '', conditions: [], disabled: false }]], [[]]] };
                        }
                    } else {
                        for (var i = 0; i < this.flows.length; i++) {
                            if (this.flows[i].name == flow.name) {
                                this.flows[i] = flow;
                                this.show(flow.name);
                                return true;
                            }
                        }
                    }
                    this.flows.push(flow);
                    flows_nav.find('.sb-active').sbActive(false);
                    flows_nav.append(this.navCode(flow.name, flow.label, true));
                    this.show(flow.name);
                },

                get: function (name = false) {
                    if (!name) {
                        name = this.getActiveName();
                    }
                    for (var i = 0; i < this.flows.length; i++) {
                        if (this.flows[i].name == name) {
                            if (!this.flows[i].steps) {
                                this.flows[i].steps = [];
                            }
                            return this.flows[i];
                        }
                    }
                    return false;
                },

                show: function (name = false) {
                    if (!name) {
                        name = this.getActiveName();
                    }
                    let flow = this.get(name);
                    let code = '';
                    let items;
                    if (flow) {
                        let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                        let previous_labels = [];
                        let labels = [];
                        for (var i = 0; i < flow.steps.length; i++) {
                            let block_cnts = flow.steps[i];
                            let letters_index = 0;
                            previous_labels = labels;
                            labels = [];
                            code += '<div><div>';
                            for (var j = 0; j < block_cnts.length; j++) {
                                let blocks = block_cnts[j];
                                code += '<div class="sb-flow-block-cnt">';
                                if (previous_labels[j]) {
                                    code += `<div class="sb-flow-block-cnt-name">${previous_labels[j]}</div>`;
                                }
                                for (var y = 0; y < blocks.length; y++) {
                                    let text = blocks[y].message ? (Array.isArray(blocks[y].message) ? (blocks[y].message.length ? blocks[y].message[0].message : '') : blocks[y].message) : '';
                                    if (text) {
                                        text = `<div>${text.length > 45 ? text.substring(0, 45) + '...' : text}</div>`;
                                    }
                                    code += `<div class="sb-flow-block" data-type="${blocks[y].type}"><div>${sb_(SBF.slugToString(blocks[y].type))}</div>${text}`;
                                    switch (blocks[y].type) {
                                        case 'get_user_details':
                                            labels.push(false);
                                            break;
                                        case 'condition':
                                        case 'choices':
                                        case 'button_list': // Deprecated
                                            let is_condition = blocks[y].type == 'condition';
                                            let rows = is_condition ? [sb_('True'), sb_('False')] : blocks[y].options;
                                            if (is_condition) {
                                                code += `<div>`;
                                                items = blocks[y].conditions;
                                                for (var x = 0; x < items.length; x++) {
                                                    code += `<div>${SBF.slugToString(items[x][0] + ' ' + items[x][1])}${items[x][2] ? ': ' + items[x][2] : ''}</div>`;
                                                }
                                                code += `</div>`;
                                            }
                                            code += `<div class="sb-flow-connectors">`;
                                            for (var x = 0; x < rows.length; x++) {
                                                labels.push(letters[letters_index] + (x + 1));
                                                code += `<div>${rows[x].replaceAll('\\,', ', ')}<span>${labels[labels.length - 1]}</span></div>`;
                                            }
                                            code += `</div>`;
                                            letters_index++;
                                            break;
                                        case 'video':
                                            code += `<div>${blocks[y].url}</div>`;
                                            break;
                                        case 'action':
                                        case 'set_data':
                                            code += `<div>`;
                                            items = blocks[y][blocks[y].type == 'set_data' ? 'data' : 'actions'];
                                            for (var x = 0; x < items.length; x++) {
                                                code += `<div>${SBF.slugToString(items[x][0])}${items[x][1] ? ': ' + items[x][1] : ''}</div>`;
                                            }
                                            code += `</div>`;
                                            break;
                                        case 'rest_api':
                                            code += `<div>${blocks[y].url}</div>`;
                                            break;
                                        case 'flow_connector':
                                            code += `<div>${blocks[y].flow_name}</div>`;
                                            break;
                                    }
                                    code += '</div>';
                                }
                                if (blocks.length < 4) {
                                    code += '<div class="sb-flow-add-block sb-icon-plus"></div>';
                                }
                                code += '</div>';
                            }
                            code += '</div><div class="sb-flow-add-step sb-icon-plus"></div></div>';
                        }
                        flows_area.html(code);
                        $(admin).find('.sb-flow-scroll').sbActive((flow.steps.length * 250) > flows_area.outerWidth());
                    }
                },

                delete: function (flow_name) {
                    for (var i = 0; i < this.flows.length; i++) {
                        if (this.flows[i].name == flow_name) {
                            let nav = flows_nav.find(`[data-value="${flow_name}"]`);
                            this.flows[i].steps.forEach((step) => {
                                step.forEach((block_cnt) => {
                                    block_cnt.forEach((block) => {
                                        if (block.attachments) {
                                            block.attachments.forEach((attachment) => {
                                                SBF.ajax({ function: 'delete-file', path: attachment });
                                            });
                                        }
                                    });
                                });
                            });
                            this.flows.splice(i, 1);
                            if (nav.sbActive()) {
                                if (nav.prev().length) {
                                    nav.prev().click();
                                } else if (nav.next().length) {
                                    nav.next().click();
                                } else {
                                    flows_area.html('');
                                }
                            }
                            nav.remove();
                            return true;
                        }
                    }
                    return false;
                },

                save: function (onSuccess = false) {
                    SBF.ajax({ function: 'open-ai-flows-save', flows: JSON.stringify(this.flows) }, (response) => {
                        onSuccess(response);
                    });
                },

                navCode: function (name, label, active = false) {
                    return `<li${active ? ' class="sb-active"' : ''} data-value="${name}">${label ? label : name}<i class="sb-icon-delete"></i></li>`; // Deprecated: replace "label ? label : name" with "label"
                },

                getActive: function () {
                    return flows_nav.find('.sb-active');
                },

                getActiveName: function () {
                    return this.getActive().attr('data-value');
                },

                getActiveIndex: function () {
                    return this.getActive().index();
                },

                steps: {

                    get: function (flow_name = false, step_index = false) {
                        return SBApps.openAI.flows.get(flow_name).steps[step_index ? step_index : this.getActiveIndex()];
                    },

                    getActiveIndex: function () {
                        return SBApps.openAI.flows.blocks.getActive().parent().parent().parent().index();
                    }
                },

                blocks: {
                    set: function (block, flow_name = false, step_index = false, block_cnt_index = false, block_index = false) {
                        let indexes = this.getIndexes(flow_name, step_index, block_cnt_index, block_index);
                        let flow = SBApps.openAI.flows.get(flow_name);
                        if (flow) {
                            let stop = false;
                            if (flow.steps.length > indexes.step) {
                                let block_cnts = flow.steps[indexes.step];
                                if (block_cnts.length > indexes.cnt) {
                                    let blocks = block_cnts[indexes.cnt];
                                    if (blocks.length > indexes.block) {
                                        blocks[indexes.block] = block;
                                        stop = true;
                                    }
                                }
                                if (!stop) {
                                    flow.steps[indexes.step][indexes.cnt].push(block);
                                    stop = true;
                                }
                            }
                            if (!stop) {
                                flow.steps.push([[block]]);
                            }

                            // Generate next step
                            let step = flow.steps[indexes.step];
                            let next_step = flow.steps[SBApps.openAI.flows.steps.getActiveIndex() + 1];
                            let next_step_block_cnts_count = 0;
                            for (var i = 0; i < step.length; i++) {
                                for (var j = 0; j < step[i].length; j++) {
                                    switch (step[i][j].type) {
                                        case 'get_user_details':
                                            next_step_block_cnts_count += 1;
                                            break;
                                        case 'choices':
                                        case 'button_list': // Deprecated
                                            next_step_block_cnts_count += step[i][j].options.length;
                                            break;
                                        case 'condition':
                                            next_step_block_cnts_count += 2;
                                            break;
                                    }
                                }
                            }
                            if (next_step) {
                                if (next_step.length > next_step_block_cnts_count) {
                                    next_step.splice((next_step_block_cnts_count - 1) * -1, next_step_block_cnts_count);
                                } else {
                                    let i = next_step.length;
                                    for (i; i < next_step_block_cnts_count; i++) {
                                        next_step.splice(indexes.cnt, 0, [])
                                    }
                                }
                            } else {
                                next_step = [];
                                for (var i = 0; i < next_step_block_cnts_count; i++) {
                                    next_step.push([]);
                                }
                                if (next_step.length) {
                                    flow.steps.push(next_step);
                                }
                            }

                            // Update the flow
                            SBApps.openAI.flows.show(flow_name);
                            return true;
                        }
                        return false;
                    },

                    get: function (flow_name = false, step_index = false, block_cnt_index = false, block_index = false) {
                        let flow = SBApps.openAI.flows.get(flow_name);
                        if (flow) {
                            let indexes = this.getIndexes(flow_name, step_index, block_cnt_index, block_index);
                            return flow.steps[indexes.step][indexes.cnt][indexes.block];
                        }
                        return false;
                    },

                    add: function (block_type, flow_name = false, step_index = false, block_cnt_index = false, block_index = false) {
                        let attributes = { button_list: { message: '', options: [] }, choices: { message: '', options: [], conversational_mode: false }, message: { message: '' }, video: { message: '', url: '' }, get_user_details: { message: '', details: [] }, set_data: { data: [] }, action: { actions: [] }, rest_api: { url: '', method: '', headers: [], body: '', save_response: [] }, condition: { conditions: [] }, tools: { message: '', url: '', method: '', headers: [], properties: [] }, flow_connector: { flow_name: '' } }; // Deprecated: remove button_list: { message: '', options: [] }
                        let indexes = this.getIndexes(flow_name, step_index, block_cnt_index, block_index);
                        this.set(Object.assign(attributes[block_type], { type: block_type }), indexes.name, indexes.step, indexes.cnt, indexes.block);
                        SBApps.openAI.flows.show(flow_name);
                        setTimeout(() => {
                            flows_area.find('> div').eq(indexes.step).find('.sb-flow-block-cnt').eq(indexes.cnt).find('.sb-flow-block').eq(indexes.block).click();
                        }, 100);
                    },

                    delete: function (flow_name = false, step_index = false, block_cnt_index = false, block_index = false) {
                        let indexes = this.getIndexes(flow_name, step_index, block_cnt_index, block_index);
                        for (var i = 0; i < SBApps.openAI.flows.flows.length; i++) {
                            let flow = SBApps.openAI.flows.flows[i];
                            if (indexes.name == flow.name) {
                                if (['get_user_details', 'button_list', 'choices', 'condition', 'tools'].includes(flow.steps[indexes.step][indexes.cnt][indexes.block].type)) { // Deprecated: remove 'button_list'
                                    let block_cnts_to_delete = this.delete_(i, indexes.step, indexes.cnt);
                                    let flow_new = Object.assign({}, flow);
                                    for (var j = 0; j < block_cnts_to_delete.length; j++) {
                                        flow.steps[block_cnts_to_delete[j][0]][block_cnts_to_delete[j][1]] = false;
                                    }
                                    flow.steps[indexes.step][indexes.cnt].splice(indexes.block, 1);
                                    flow_new.steps = [];
                                    for (var j = 0; j < flow.steps.length; j++) {
                                        let step = [];
                                        for (var k = 0; k < flow.steps[j].length; k++) {
                                            if (flow.steps[j][k]) {
                                                step.push(flow.steps[j][k]);
                                            }
                                        }
                                        if (step.length) {
                                            flow_new.steps.push(step);
                                        }
                                    }
                                    SBApps.openAI.flows.flows[i] = flow_new;
                                } else {
                                    flow.steps[indexes.step][indexes.cnt].splice(indexes.block, 1);
                                }
                                SBApps.openAI.flows.show(indexes.name);
                                return true;
                            }
                        }
                        return false;
                    },

                    delete_: function (i, step_index, block_cnt_index, all_next_block_cnt_indexes = []) {
                        let next_block_cnt_indexes = SBApps.openAI.flows.blocks.getNextCntIndexes(i, step_index, block_cnt_index);
                        for (var j = 0; j < next_block_cnt_indexes.length; j++) {
                            all_next_block_cnt_indexes.push([step_index + 1, next_block_cnt_indexes[j]]);
                            this.delete_(i, step_index + 1, next_block_cnt_indexes[j], all_next_block_cnt_indexes);
                        }
                        return all_next_block_cnt_indexes;
                    },

                    getActive: function () {
                        return flows_area.find('.sb-flow-add-block.sb-active, .sb-flow-block.sb-active');
                    },

                    getActiveIndex: function () {
                        let blocks = this.getActiveCnt().find('.sb-flow-block');
                        let index = blocks.index(this.getActive());
                        return index === -1 ? blocks.length : index;
                    },

                    getActiveCnt: function () {
                        return this.getActive().parent();
                    },

                    getActiveCntIndex: function () {
                        return this.getActive().parent().index();
                    },

                    getNextCnt: function (current_flow_index, current_step_index, current_block_cnts_index, current_connector_index = 0) {
                        let indexes = this.getNextCntIndexes(current_flow_index, current_step_index, current_block_cnts_index, current_connector_index);
                        return indexes.length > current_connector_index ? SBApps.openAI.flows.flows[current_flow_index].steps[current_step_index + 1][indexes[current_connector_index]] : false;
                    },

                    getNextCntIndexes: function (current_flow_index, current_step_index, current_block_cnt_index) {
                        let flow = SBApps.openAI.flows.flows[current_flow_index];
                        let next_block_cnt_indexees = [];
                        if (flow && flow.steps[current_step_index + 1]) {
                            let next_block_cnt_index = 0;
                            for (var i = 0; i <= current_block_cnt_index; i++) {
                                let current_blocks = flow.steps[current_step_index][i];
                                for (var j = 0; j < current_blocks.length; j++) {
                                    if (current_blocks[j].type == 'button_list' || current_blocks[j].type == 'choices') { // Deprecated: remove 'button_list'
                                        for (var k = 0; k < current_blocks[j].options.length; k++) {
                                            if (i == current_block_cnt_index) {
                                                next_block_cnt_indexees.push(next_block_cnt_index);
                                            }
                                            next_block_cnt_index++;
                                        }
                                    } else if (current_blocks[j].type == 'get_user_details') {
                                        if (i == current_block_cnt_index) {
                                            next_block_cnt_indexees.push(next_block_cnt_index);
                                        }
                                        next_block_cnt_index++;
                                    } else if (current_blocks[j].type == 'condition') {
                                        for (var k = 0; k < 2; k++) {
                                            if (i == current_block_cnt_index) {
                                                next_block_cnt_indexees.push(next_block_cnt_index);
                                            }
                                            next_block_cnt_index++;
                                        }
                                    }
                                }
                            }
                        }
                        return next_block_cnt_indexees;
                    },

                    getPreviousCntIndex: function (current_flow_index, current_step_index, current_block_cnt_index) {
                        let previous_step = SBApps.openAI.flows.flows[current_flow_index].steps[current_step_index - 1];
                        if (previous_step) {
                            let index = 0;
                            for (var i = 0; i < previous_step.length; i++) {
                                let block_cnt = previous_step[i];
                                for (var j = 0; j < block_cnt.length; j++) {
                                    index += block_cnt[j].type == 'button_list' || block_cnt[j].type == 'choices' ? block_cnt[j].options.length : (block_cnt[j].type == 'get_user_details' ? 1 : (block_cnt[j].type == 'condition' ? 2 : 0)); // Deprecated: remove 'button_list'
                                }
                                if (index > current_block_cnt_index) {
                                    return i;
                                }
                            }
                            return index;
                        }
                    },

                    getIndexes: function (flow_name, step_index, block_cnt_index, block_index) {
                        return { name: flow_name ? flow_name : SBApps.openAI.flows.getActiveName(), step: step_index ? step_index : SBApps.openAI.flows.steps.getActiveIndex(), cnt: block_cnt_index ? block_cnt_index : this.getActiveCntIndex(), block: block_index ? block_index : this.getActiveIndex() };
                    },

                    activateLinkedCnts: function (active_block) {
                        let block_cnt = $(active_block).parent();
                        let active_flow_index = SBApps.openAI.flows.getActiveIndex();
                        let active_step_index = block_cnt.parent().parent().index();
                        let flows = flows_area.find('> div');
                        let previous_cnt = flows.eq(active_step_index - 1).find('.sb-flow-block-cnt').eq(SBApps.openAI.flows.blocks.getPreviousCntIndex(active_flow_index, active_step_index, block_cnt.index()));
                        if (!is_over_connector) {
                            let next_block_cnts = flows.eq(active_step_index + 1).find('.sb-flow-block-cnt');
                            let next_block_cnt_indexes = SBApps.openAI.flows.blocks.getNextCntIndexes(active_flow_index, active_step_index, block_cnt.index());
                            for (var i = 0; i < next_block_cnt_indexes.length; i++) {
                                next_block_cnts.eq(next_block_cnt_indexes[i]).sbActive(true);
                            }
                        }
                        flows_area.find('.sb-flow-connectors > div').sbActive(false);
                        previous_cnt.sbActive(true).find('.sb-flow-block-cnt-name').sbActive(true);
                        if (block_cnt.find('.sb-flow-block-cnt-name').length) {
                            previous_cnt.find('.sb-flow-connectors > div').sbActive(false).eq(parseInt(block_cnt.find('.sb-flow-block-cnt-name').html().substring(1)) - 1).sbActive(true);
                        }
                    }
                }
            },

            train: {
                urls: [],
                errors: [],
                base_url: false,
                start_urls: [],
                sitemap_processed_urls: [],
                active_source: false,
                history: [],
                training_button: false,
                extract_url: [],
                skip_files: [],

                files: function (onSuccess, index = 0) {
                    let files = upload_input.prop('files');
                    if (index >= files.length) {
                        return onSuccess(true);
                    }
                    let file_name = files[index].name;
                    if (this.isFile(file_name) && !this.skip_files.includes(file_name)) {
                        admin.find('#sb-embeddings-box p').html(`<span>${sb_('We are processing the source')}</span><pre>${file_name}</pre><span>${sb_('Only {R} sources left to complete.').replace('{R}', files.length - index)}</span>`);
                        upload_input.sbUploadFiles((response) => {
                            response = JSON.parse(response);
                            if (response[0] == 'success') {
                                SBF.ajax({ function: 'open-ai-file-training', url: response[1] }, (response) => {
                                    if (this.isError(response)) {
                                        return;
                                    }
                                    this.files(onSuccess, index + 1);
                                });
                            }
                        }, index);
                    } else {
                        this.files(onSuccess, index + 1);
                    }
                },

                website: function (onSuccess, index = 0) {
                    if (index >= this.urls.length) {
                        return onSuccess(true);
                    }
                    let url = this.urls[index];
                    if (url && url.includes('http')) {
                        admin.find('#sb-embeddings-box p').html(`<span>${sb_('We are processing the source')}<pre>${url}</pre><span>${sb_('Only {R} sources left to complete.').replace('{R}', this.urls.length - index)}</span>`);
                        if (url.includes('.xml')) {
                            SBF.ajax({ function: 'get-sitemap-urls', sitemap_url: url }, (response) => {
                                if (Array.isArray(response)) {
                                    this.urls = this.urls.concat(response);
                                } else {
                                    this.errors.push(response);
                                }
                                this.website(onSuccess, index + 1);
                            });
                        } else if (!this.sitemap_processed_urls.includes(url) && this.extract_url[index]) {
                            this.sitemap_processed_urls.push(url);
                            this.sitemap(url, (response) => {
                                this.urls = this.urls.concat(response);
                                this.website(onSuccess, index + 1);
                            });
                        } else {
                            SBF.ajax({ function: 'open-ai-url-training', url: url }, (response) => {
                                if (this.isError(response)) {
                                    return;
                                } else if (!response[0] && !response[1].includes('http-error-404') && !response[1].includes('http-error-302')) {
                                    if (response[1].includes('http-error') && index === 0) {
                                        this.errors.push(response[2]);
                                    } else if (response[0][0] !== true) {
                                        this.errors.push(response);
                                    }
                                }
                                this.website(onSuccess, index + 1);
                            });
                        }
                    } else {
                        if (url) {
                            this.errors.push(sb_('Use a valid URL starting with http. The URL {R} is not valid.').replace('{R}', url));
                        }
                        this.website(onSuccess, index + 1);
                    }
                },

                sitemap: function (url, onSuccess) {
                    admin.find('#sb-embeddings-box p').html(`<span>${sb_('We are generating the sitemap')}</span><pre>${url}</pre>`);
                    SBF.ajax({ function: 'generate-sitemap', url: url }, (response) => {
                        onSuccess(response);
                    });
                },

                qea: function (onSuccess) {
                    admin.find('#sb-embeddings-box p').html(sb_('We are processing the Q&A.'));
                    let questions_answers = SBSettings.repeater.get(chatbot_qea_repeater.find('.sb-repeater').eq(0).find('> .repeater-item')).map((item) => {
                        return [
                            item['open-ai-faq-questions'].map((item) => {
                                return item.question;
                            }),
                            item['open-ai-faq-answer'],
                            item['open-ai-faq-function-calling-url'],
                            item['open-ai-faq-function-calling-method'],
                            item['open-ai-faq-function-calling-headers'],
                            item['open-ai-faq-function-calling-properties'].length ? item['open-ai-faq-function-calling-properties'].map((item) => {
                                return [item.name, item.description, item.allowed];
                            }) : false,
                            item['open-ai-faq-set-data'].map((item) => {
                                return [item.id, item.value];
                            })
                        ];
                    });
                    SBF.ajax({
                        function: 'open-ai-qea-training',
                        questions_answers: questions_answers,
                        reset: true
                    }, (response) => {
                        onSuccess(response);
                    });
                },

                articles: function (onSuccess) {
                    admin.find('#sb-embeddings-box p').html(sb_('We are processing the articles.'));
                    SBF.ajax({ function: 'open-ai-articles-training' }, (response) => {
                        onSuccess(response);
                    });
                },

                isFile: function (url) {
                    return url.includes('.pdf') || url.includes('.txt') || url.includes('.json') || url.includes('.csv');
                },

                isError: function (response) {
                    let is_limit = response[1] == 'chars-limit-exceeded';
                    let is_error = is_limit || (response[1] && response[1][0] && response[1][0].error);
                    if (is_error) {
                        chatbot_area.find('#sb-train-chatbot').sbLoading(false);
                        infoPanel(is_limit ? sb_('The chatbot cannot be trained with these sources because the limit of your plan is {R} characters. Upgrade your plan to increase the number of characters.').replace('{R}', response[2]) : response[1][0].error.message);
                    }
                    return is_error;
                }
            },

            playground: {
                last_response: false,
                history: false,

                deleteData: function (action = 'delete', onSuccess = false, extra = false) {
                    SBF.ajax({
                        function: 'open-ai-playground-data',
                        action: action,
                        extra: extra
                    }, (response) => {
                        if (action == 'delete') {
                            this.last_response = false;
                        }
                        if (onSuccess) {
                            onSuccess(response);
                        }
                    });
                }
            },

            init: function () {
                SBF.ajax({
                    function: 'open-ai-get-training-files'
                }, (response) => {
                    let code = ['', ''];
                    for (var i = 0; i < response.length; i++) {
                        if (!['sb-conversations', 'sb-articles', 'sb-database', 'sb-flows'].includes(response[i])) {
                            let is_file = this.train.isFile(response[i]);
                            code[is_file ? 1 : 0] += `<tr data-url="${response[i]}"><td><input type="checkbox" /></td><td>${is_file ? SBF.beautifyAttachmentName(response[i].split('/').pop()) : urlStrip(response[i])}</td><td></td><td><i class="sb-icon-delete"></i></td></tr>`;
                        }
                    }
                    chatbot_files_table.sbLoading(false).find('tbody').html(code[1]);
                    chatbot_website_table.sbLoading(false).find('tbody').html(code[0]);
                    chatbot_area.find('#sb-chatbot-delete-files, #sb-table-chatbot-files').setClass('sb-hide', !code[1]);
                    chatbot_area.find('#sb-chatbot-delete-website, #sb-table-chatbot-website').setClass('sb-hide', !code[0]);
                });
                SBF.ajax({
                    function: 'open-ai-get-qea-training'
                }, (response) => {
                    for (var i = 0; i < response.length; i++) { // Deprecated
                        if (response[i][0] && !Array.isArray(response[i][0])) { // Deprecated
                            response[i][0] = [response[i][0]]; // Deprecated
                        } // Deprecated
                    } // Deprecated
                    let faq = response.map(item => ({
                        'open-ai-faq-questions': item[0] ? item[0].map(item => ({ question: item })) : [''],
                        'open-ai-faq-answer': item[1],
                        'open-ai-faq-function-calling-url': item[2],
                        'open-ai-faq-function-calling-method': item[3],
                        'open-ai-faq-function-calling-headers': item[4],
                        'open-ai-faq-function-calling-properties': item[5] && item[5].length ? item[5].map(item => ({ name: item[0], description: item[1], allowed: item[2] })) : [['', '', '']],
                        'open-ai-faq-set-data': item[6] && item[6].length ? item[6].map(item => ({ id: item[0], value: item[1] })) : [['', '']],
                    }));
                    if (faq.length) {
                        chatbot_qea_repeater.find('> div > .sb-repeater').html(SBSettings.repeater.set(faq, chatbot_qea_repeater.find('> div > .sb-repeater > .repeater-item:last-child')));
                        chatbot_qea_repeater.find('.sb-enlarger').each(function () {
                            let selects = $(this).find('select');
                            let no_value_keys = ['transcript', 'transcript_email', 'human_takeover', 'archive_conversation'];
                            if ($(this).find('input').val() || no_value_keys.includes(selects.val())) {
                                $(this).sbActive(true);
                                if ($(this).hasClass('sb-enlarger-function-calling')) {
                                    $(this).closest('.repeater-item').find('.sb-qea-repeater-answer').addClass('sb-hide');
                                }
                            }
                            selects.each(function () {
                                if (no_value_keys.includes($(this).val())) {
                                    $(this).parent().next().find('input').addClass('sb-hide');
                                }
                            });
                        });
                    }
                });
            }
        },

        messenger: {

            check: function (conversation) {
                return ['fb', 'ig'].includes(conversation.get('source'));
            },

            send: function (PSID, facebook_page_id, message = '', attachments = [], metadata, message_id = false, reply_to = false, onSuccess = false) {
                SBF.ajax({
                    function: 'messenger-send-message',
                    psid: PSID,
                    facebook_page_id: facebook_page_id,
                    message: message,
                    message_id: message_id,
                    attachments: attachments,
                    metadata: metadata,
                    reply_to: reply_to
                }, (response) => {
                    if (onSuccess) {
                        onSuccess(response);
                    }
                    SBApps.unsupportedRichMessages(message, 'Messenger');
                });
            },

            sendComment: function (comment_id, facebook_page_id, message, message_id, is_instagram = true, onSuccess = false) {
                SBF.ajax({
                    function: 'messenger-send-comment',
                    comment_id: comment_id,
                    facebook_page_id: facebook_page_id,
                    message_id: message_id,
                    message: message,
                    is_instagram: is_instagram
                }, (response) => {
                    if (onSuccess) {
                        onSuccess(response);
                    }
                    SBApps.unsupportedRichMessages(message, 'Messenger');
                });
            }
        },

        whatsapp: {

            check: function (conversation) {
                return conversation.get('source') == 'wa';
            },

            send: function (to, message = '', attachments = [], phone_id = false, reply_to = false, message_id = false, onSuccess = false) {
                SBF.ajax({
                    function: 'whatsapp-send-message',
                    to: to,
                    message: message,
                    attachments: attachments,
                    phone_id: phone_id,
                    reply_to: reply_to,
                    message_id: message_id
                }, (response) => {
                    if (response.error) {
                        infoPanel(response.error.message, 'info', false, 'error-wa');
                    }
                    if (onSuccess) {
                        onSuccess(response);
                    }
                    SBApps.unsupportedRichMessages(message, 'WhatsApp');
                });
            },

            activeUserPhone: function (user = activeUser()) {
                return user.getExtra('phone') ? user.getExtra('phone').value.replace('+', '') : false
            }
        },

        telegram: {

            check: function (conversation) {
                return conversation.get('source') == 'tg';
            },

            send: function (chat_id, message = '', attachments = [], conversation_id = false, reply_to = false, message_id = false, onSuccess = false) {
                SBF.ajax({
                    function: 'telegram-send-message',
                    chat_id: chat_id,
                    message: message,
                    message_id: message_id,
                    attachments: attachments,
                    conversation_id: conversation_id,
                    reply_to: reply_to
                }, (response) => {
                    if (onSuccess) onSuccess(response);
                    SBApps.unsupportedRichMessages(message, 'Telegram');
                });
            }
        },

        viber: {

            check: function (conversation) {
                return conversation.get('source') == 'vb';
            },

            send: function (viber_id, message = '', attachments = [], onSuccess = false) {
                SBF.ajax({
                    function: 'viber-send-message',
                    viber_id: viber_id,
                    message: message,
                    attachments: attachments
                }, (response) => {
                    if (onSuccess) onSuccess(response);
                    SBApps.unsupportedRichMessages(message, 'Viber');
                });
            }
        },

        zalo: {

            check: function (conversation) {
                return conversation.get('source') == 'za';
            },

            send: function (zalo_id, message = '', attachments = [], onSuccess = false) {
                SBF.ajax({
                    function: 'zalo-send-message',
                    zalo_id: zalo_id,
                    message: message,
                    attachments: attachments
                }, (response) => {
                    if (onSuccess) onSuccess(response);
                    SBApps.unsupportedRichMessages(message, 'Zalo');
                });
            }
        },

        twitter: {

            check: function (conversation) {
                return conversation.get('source') == 'tw';
            },

            send: function (twitter_id, message = '', attachments = [], onSuccess = false) {
                SBF.ajax({
                    function: 'twitter-send-message',
                    twitter_id: twitter_id,
                    message: message,
                    attachments: attachments
                }, (response) => {
                    if (onSuccess) onSuccess(response);
                    SBApps.unsupportedRichMessages(message, 'Twitter');
                });
            }
        },

        line: {
            check: function (conversation) {
                return conversation.get('source') == 'ln';
            },

            send: function (line_id, message = '', attachments = [], conversation_id = false, onSuccess = false) {
                SBF.ajax({
                    function: 'line-send-message',
                    line_id: line_id,
                    message: message,
                    attachments: attachments,
                    conversation_id: conversation_id
                }, (response) => {
                    if (onSuccess) onSuccess(response);
                    SBApps.unsupportedRichMessages(message, 'LINE');
                });
            }
        },

        wechat: {
            token: false,

            check: function (conversation) {
                return conversation.get('source') == 'wc';
            },

            send: function (open_id, message = '', attachments = [], onSuccess = false) {
                SBF.ajax({
                    function: 'wechat-send-message',
                    open_id: open_id,
                    message: message,
                    attachments: attachments,
                    token: this.token
                }, (response) => {
                    if (Array.isArray(response)) {
                        this.token = response[1];
                        response = response[0];
                    }
                    if (onSuccess) onSuccess(response);
                    SBApps.unsupportedRichMessages(message, 'WeChat');
                });
            }
        },

        aecommerce: {

            conversationPanel: function () {
                let code = '';
                let aecommerce_id = activeUser().getExtra('aecommerce-id');
                if (!this.panel) this.panel = conversations_area.find('.sb-panel-aecommerce');
                if (aecommerce_id && !loading(this.panel)) {
                    SBF.ajax({
                        function: 'aecommerce-get-conversation-details',
                        aecommerce_id: aecommerce_id.value
                    }, (response) => {
                        code = `<h3>${SB_ADMIN_SETTINGS.aecommerce_panel_title}</h3><div><div class="sb-split"><div><div class="sb-title">${sb_('Number of orders')}</div><span>${response.orders_count} ${sb_('orders')}</span></div><div><div class="sb-title">${sb_('Total spend')}</div><span>${response.total} ${response.currency_symbol}</span></div></div><div class="sb-title">${sb_('Cart')}</div><div class="sb-list-items sb-list-links sb-aecommerce-cart">`;
                        for (var i = 0; i < response.cart.length; i++) {
                            let product = response.cart[i];
                            code += `<a href="${product.url}" target="_blank" data-id="${product.id}"><span>#${product.id}</span> <span>${product.name}</span> <span>x ${product.quantity}</span></a>`;
                        }
                        code += (response.cart.length ? '' : '<p>' + sb_('The cart is currently empty.') + '</p>') + '</div>';
                        if (response.orders.length) {
                            code += `<div class="sb-title">${sb_('Orders')}</div><div class="sb-list-items sb-list-links sb-aecommerce-orders">`;
                            for (var i = 0; i < response.orders.length; i++) {
                                let order = response.orders[i];
                                let id = order.id;
                                code += `<a data-id="${id}" href="${order.url}" target="_blank"><span>#${order.id}</span> <span>${SBF.beautifyTime(order.time, true)}</span> <span>${order.price} ${response.currency_symbol}</span></a>`;
                            }
                            code += '</div>';
                        }
                        $(this.panel).html(code).sbLoading(false);
                        collapse(this.panel, 160);
                    });
                }
                $(this.panel).html(code);
            }
        },

        martfury: {

            conversationPanel: function () {
                let code = '';
                let martfury_id = activeUser().getExtra('martfury-id');
                if (!this.panel) this.panel = conversations_area.find('.sb-panel-martfury');
                if (martfury_id && !loading(this.panel)) {
                    SBF.ajax({
                        function: 'martfury-get-conversation-details',
                        martfury_id: martfury_id.value
                    }, (response) => {
                        $(this.panel).html(response).sbLoading(false);
                        collapse(this.panel, 160);
                    });
                }
                $(this.panel).html(code);
            }
        },

        whmcs: {

            conversationPanel: function () {
                let code = '';
                let whmcs_id = activeUser().getExtra('whmcs-id');
                if (!this.panel) this.panel = conversations_area.find('.sb-panel-whmcs');
                if (whmcs_id && !loading(this.panel)) {
                    SBF.ajax({
                        function: 'whmcs-get-conversation-details',
                        whmcs_id: whmcs_id.value
                    }, (response) => {
                        let services = ['products', 'addons', 'domains'];
                        code = `<h3>WHMCS</h3><div><div class="sb-split"><div><div class="sb-title">${sb_('Number of services')}</div><span>${response.services_count} ${sb_('services')}</span></div><div><div class="sb-title">${sb_('Total spend')}</div><span>${response.total} ${response.currency_symbol}</span></div></div></div>`;
                        for (var i = 0; i < services.length; i++) {
                            let items = response[services[i]];
                            if (items.length) {
                                code += `<div class="sb-title">${sb_(SBF.slugToString(services[i]))}</div><div class="sb-list-items">`;
                                for (var j = 0; j < items.length; j++) {
                                    code += `<div>${items[j].name}</div>`;
                                }
                                code += '</div>';
                            }
                        }
                        code += `<a href="${SB_ADMIN_SETTINGS.whmcs_url}/clientssummary.php?userid=${response['client-id']}" target="_blank" class="sb-btn sb-whmcs-link">${sb_('View on WHMCS')}</a>`;
                        $(this.panel).html(code).sbLoading(false);
                        collapse(this.panel, 160);
                    });
                }
                $(this.panel).html(code);
            }
        },

        perfex: {

            conversationPanel: function () {
                let perfex_id = activeUser().getExtra('perfex-id');
                conversations_area.find('.sb-panel-perfex').html(perfex_id ? `<a href="${SB_ADMIN_SETTINGS.perfex_url}/admin/clients/client/${perfex_id.value}" target="_blank" class="sb-btn sb-perfex-link">${sb_('View on Perfex')}</a>` : '');
            }
        },

        calendar: {

            conversationPanel: function () {
                let panel = conversations_area.find('.sb-panel-calendar');
                panel.addClass('sb-hide');
                if (panel.length) {
                    SBF.ajax({
                        function: 'calendar-panel'
                    }, (response) => {
                        panel.find('> div').html(response);
                        panel.removeClass('sb-hide');
                    });
                }
            },

            cancelBooking: function (booking_id, onSuccess) {
                SBF.ajax({
                    function: 'calendar-cancel-booking',
                    booking_id: booking_id
                }, (response) => {
                    onSuccess(response);
                });
            },

            getAvailableSlots: function (date, onSuccess, max_days = 1) {
                SBF.ajax({
                    function: 'calendar-get-available-slots',
                    date: date,
                    max_days: max_days
                }, (response) => {
                    onSuccess(response);
                });
            },

            addBooking: function (start_date, onSuccess) {
                SBF.ajax({
                    function: 'calendar-create-booking',
                    start_date: start_date
                }, (response) => {
                    onSuccess(response);
                });
            }
        },

        ump: {

            conversationPanel: function () {
                if (loading(this.panel)) return;
                if (!this.panel) this.panel = conversations_area.find('.sb-panel-ump');
                let code = '';
                let subscriptions;
                SBF.ajax({
                    function: 'ump-get-conversation-details'
                }, (response) => {
                    subscriptions = response.subscriptions;
                    if (subscriptions.length) {
                        code = '<i class="sb-icon-refresh"></i><h3>Membership</h3><div class="sb-list-names">';
                        for (var i = 0; i < subscriptions.length; i++) {
                            let expired = subscriptions[i].expired;
                            code += `<div${expired ? ' class="sb-expired"' : ''}><span>${subscriptions[i].label}</span><span>${sb_(expired ? 'Expired on' : 'Expires on')} ${SBF.beautifyTime(subscriptions[i].expire_time, false, !expired)}</span></div>`;
                        }
                        code += `</div><span class="sb-title">${sb_('Total spend')} ${response.total} ${response.currency_symbol}</span>`;
                    }
                    $(this.panel).html(code).sbLoading(false);
                    collapse(this.panel, 160);
                });
            }
        },

        armember: {

            conversationPanel: function () {
                let wp_user_id = activeUser().getExtra('wp-id');
                if (!this.panel) this.panel = conversations_area.find('.sb-panel-armember');
                if (!SBF.null(wp_user_id) && !loading(this.panel)) {
                    let code = '';
                    let subscriptions;
                    wp_user_id = wp_user_id.value;
                    SBF.ajax({
                        function: 'armember-get-conversation-details',
                        wp_user_id: wp_user_id
                    }, (response) => {
                        subscriptions = response.subscriptions;
                        if (subscriptions.length) {
                            code = `<i class="sb-icon-refresh"></i><h3>${sb_('Plans')}</h3><div class="sb-list-names">`;
                            for (var i = 0; i < subscriptions.length; i++) {
                                let expired = subscriptions[i].expired;
                                code += `<div${expired ? ' class="sb-expired"' : ''}><span>${subscriptions[i].arm_current_plan_detail.arm_subscription_plan_name}</span><span>${subscriptions[i].expire_time == 'never' ? '' : (sb_(expired ? 'Expired on' : 'Expires on') + ' ' + SBF.beautifyTime(subscriptions[i].expire_time, false, !expired))}</span></div>`;
                            }
                            code += `</div><span class="sb-title">${sb_('Total spend')} ${response.total} ${response.currency_symbol}<a href="${window.location.href.substr(0, window.location.href.lastIndexOf('/')) + '?page=arm_manage_members&member_id=' + activeUser().getExtra('wp-id').value}" target="_blank" class="sb-btn-text"><i class="sb-icon-user"></i> ${sb_('View member')}</a></span>`;
                        }
                        $(this.panel).html(code).sbLoading(false);
                        collapse(this.panel, 160);
                    });
                } else $(this.panel).html('');
            }
        },

        zendesk: {

            conversationPanel: function () {
                if (!SB_ADMIN_SETTINGS.zendesk_active) return;
                let zendesk_id = activeUser().getExtra('zendesk-id');
                let phone = activeUser().getExtra('phone');
                let email = activeUser().get('email');
                let panel = conversations_area.find('.sb-panel-zendesk');
                if ((zendesk_id || phone || email) && !loading(panel)) {
                    SBF.ajax({
                        function: 'zendesk-get-conversation-details',
                        conversation_id: SBChat.conversation.id,
                        zendesk_id: zendesk_id ? zendesk_id.value : false,
                        phone: phone ? phone.value : false,
                        email: email,
                    }, (response) => {
                        $(panel).html(response).sbLoading(false);
                        panel.find('.sb-zendesk-date').each(function () {
                            $(this).html(SBF.beautifyTime($(this).html()));
                        });
                        collapse(panel, 160);
                    });
                } else $(panel).html('');
            }
        },

        woocommerce: {
            timeout: false,

            conversationPanel: function () {
                if (loading(this.panel)) {
                    return;
                }
                if (!this.panel) {
                    this.panel = conversations_area.find('.sb-panel-woocommerce');
                }
                let code = '';
                SBF.ajax({
                    function: 'woocommerce-get-conversation-details'
                }, (response) => {
                    code = `<i class="sb-icon-refresh"></i><h3>WooCommerce</h3><div><div class="sb-split"><div><div class="sb-title">${sb_('Number of orders')}</div><span>${response.orders_count} ${sb_('orders')}</span></div><div><div class="sb-title">${sb_('Total spend')}</div><span>${response.total} ${response.currency_symbol}</span></div></div><div class="sb-title">${sb_('Cart')}<i class="sb-add-cart-btn sb-icon-plus"></i></div><div class="sb-list-items sb-list-links sb-woocommerce-cart">`;
                    for (var i = 0; i < response.cart.length; i++) {
                        let product = response.cart[i];
                        code += `<a href="${product.url}" target="_blank" data-id="${product.id}"><span>#${product.id}</span> <span>${product.name}</span> <span>x ${product.quantity}</span><i class="sb-icon-close"></i></a>`;
                    }
                    code += (response.cart.length ? '' : '<p>' + sb_('The cart is currently empty.') + '</p>') + '</div>';
                    if (response.orders.length) {
                        code += `<div class="sb-title">${sb_('Orders')}</div><div class="sb-list-items sb-woocommerce-orders sb-accordion">`;
                        for (var i = 0; i < response.orders.length; i++) {
                            let order = response.orders[i];
                            let id = order.id;
                            code += `<div data-id="${id}"><span><span>#${id}</span> <span>${SBF.beautifyTime(order.date, true)}</span><a href="${SITE_URL}/wp-admin/post.php?post=${id}&action=edit" target="_blank" class="sb-icon-next"></a></span><div></div></div>`;
                        }
                        code += '</div>';
                    }
                    $(this.panel).html(code).sbLoading(false);
                    collapse(this.panel, 160);
                });
            },

            conversationPanelOrder: function (order_id) {
                let accordion = this.panel.find(`[data-id="${order_id}"] > div`);
                accordion.html('');
                SBF.ajax({
                    function: 'woocommerce-get-order',
                    order_id: order_id
                }, (response) => {
                    let code = '';
                    let collapse = this.panel.find('.sb-collapse-btn:not(.sb-active)');
                    if (response) {
                        let products = response.products;
                        code += `<div class="sb-title">${sb_('Order total')}: <span>${response.total} ${response.currency_symbol}<span></div><div class="sb-title">${sb_('Order status')}: <span>${SBF.slugToString(response.status.replace('wc-', ''))}<span></div><div class="sb-title">${sb_('Date')}: <span>${SBF.beautifyTime(response.date, true)}<span></div><div class="sb-title">${sb_('Products')}</div>`;
                        for (var i = 0; i < products.length; i++) {
                            code += `<a href="${SITE_URL}?p=${products[i].id}" target="_blank"><span>#${products[i].id}</span> <span>${products[i].quantity} x</span> <span>${products[i].name}</span></a>`;
                        }
                        for (var i = 0; i < 2; i++) {
                            let key = i == 0 ? 'shipping' : 'billing';
                            if (response[key + '_address']) {
                                code += `<div class="sb-title">${sb_((i == 0 ? 'Shipping' : 'Billing') + ' address')}</div><div class="sb-multiline">${response[key + '_address'].replace(/\\n/g, '<br>')}</div>`;
                            }
                        }
                    }
                    if (collapse.length) {
                        collapse.click();
                    }
                    accordion.html(code);
                });
            },

            conversationPanelUpdate: function (product_id, action = 'added') {
                let busy = false;
                let count = 0;
                this.timeout = setInterval(() => {
                    if (!busy) {
                        SBF.ajax({
                            function: 'woocommerce-get-conversation-details'
                        }, (response) => {
                            let removed = true;
                            for (var i = 0; i < response.cart.length; i++) {
                                if (response.cart[i].id == product_id) {
                                    if (action == 'added') {
                                        count = 61;
                                    } else {
                                        removed = false;
                                    }
                                }
                            }
                            if (count > 60 || removed) {
                                this.conversationPanel();
                                conversations_area.find('.sb-add-cart-btn,.sb-woocommerce-cart > a i').sbLoading(false);
                                clearInterval(this.timeout);
                            }
                            count++;
                            busy = false;
                        });
                        busy = true;
                    }
                }, 1000);
            }
        },

        opencart: {

            conversationPanel: function () {
                let panel = conversations_area.find('.sb-panel-opencart');
                let opencart_id = activeUser().getExtra('opencart_id');
                let store_url = activeUser().getExtra('opencart_store_url');
                if (!opencart_id) {
                    return panel.html('');
                }
                if (loading(panel)) {
                    return;
                }
                SBF.ajax({
                    function: 'opencart-panel',
                    opencart_id: opencart_id.value,
                    store_url: store_url ? store_url.value : false,
                }, (response) => {
                    panel.html(response).sbLoading(false);
                    collapse(this.panel, 160);
                });
            },

            openOrder: function (order_id) {
                SBF.ajax({
                    function: 'opencart-order-details',
                    order_id: order_id
                }, (response) => {
                    SBAdmin.infoPanel(response, 'info', false, 'opencart-order-details', sb_('Order') + ' #' + order_id, true);
                });
            }
        },

        wordpress: {
            ajax: function (action, data, onSuccess) {
                $.ajax({
                    method: 'POST',
                    url: SB_WP_AJAX_URL,
                    data: $.extend({ action: 'sb_wp_ajax', type: action }, data)
                }).done((response) => {
                    if (onSuccess !== false) {
                        onSuccess(response);
                    }
                });
            }
        },

        is: function (name) {
            if (typeof SB_VERSIONS == ND) {
                return false;
            }
            switch (name) {
                case 'opencart':
                case 'zendesk':
                case 'twitter':
                case 'wechat':
                case 'line':
                case 'viber':
                case 'zalo':
                case 'telegram':
                case 'armember':
                case 'aecommerce':
                case 'martfury':
                case 'whmcs':
                case 'perfex':
                case 'ump':
                case 'messenger':
                case 'whatsapp':
                case 'woocommerce':
                case 'dialogflow':
                case 'slack':
                case 'tickets': return typeof SB_VERSIONS[name] != ND && SB_VERSIONS[name];
                case 'wordpress': return typeof SB_WP != ND;
                case 'sb': return true;
            }
            return false;
        },

        unsupportedRichMessages: function (message, app_name, unsupported = []) {
            unsupported.push('timetable', 'registration', 'table', 'inputs');
            if (!['Messenger', 'WhatsApp'].includes(app_name)) {
                unsupported.push('email');
            }
            for (var i = 0; i < unsupported.length; i++) {
                if (message.includes('[' + unsupported[i])) {
                    infoBottom('The {R} rich message is not supported by {R2}. The rich message was not sent to {R2}.'.replace(/{R}/g, SBF.slugToString(unsupported[i])).replace(/{R2}/g, app_name), 'error');
                }
            }
        },

        getMessagingAppName: function (source = false) {
            let names = { fb: 'Facebook', wa: 'WhatsApp', tm: 'Text message', ig: 'Instagram', tg: 'Telegram', tk: 'Tickets', wc: 'WeChat', em: 'Email', tw: 'Twitter', vb: 'Viber', ln: 'LINE', za: 'Zalo' };
            return source ? (source in names ? names[source] : source) : names;
        },

        getSelectMessagingApps: function (active_app_code = false, include_chat = false) {
            let apps = this.getMessagingAppName();
            let code = '<select class="sb-select-messaging-apps"><option value=""></option>';
            if (include_chat) {
                apps['ch'] = 'Chat';
            }
            for (let app_code in apps) {
                code += `<option value="${app_code}"${active_app_code && active_app_code == app_code ? ' selected' : ''}>${apps[app_code]}</option>`;
            }
            return code + '</select>';
        },

        itemsPanel: {

            pagination_reference: 1,
            panel_language: '',

            code: function (items, app_name, label = true) {
                let code = '';
                for (var i = 0; i < items.length; i++) {
                    code += `<li data-id="${items[i].id.split('/').pop()}"><div class="sb-image" style="background-image:url('${items[i].image ? (app_name == 'shopify' ? items[i].image.replace('.jpg', '_small.jpg') : items[i].image) : SB_URL + '/media/thumb.svg'}')"></div><div><span>${items[i].name ? items[i].name : items[i].title}</span><span>${items[i].price ? items[i].price : items[i].variants.edges[0].node.price} ${SB_ADMIN_SETTINGS.currency}</span></div></li>`;
                }
                return label ? (code ? code : `<p class="sb-no-results">${sb_('No products found')}</p>`) : code;
            },

            getAppInfo: function (app_name) {
                switch (app_name) {
                    case 'woocommerce':
                        return { area: woocommerce_products_box, ul: woocommerce_products_box_ul, search: 'woocommerce-search-products', filter: 'woocommerce-get-products', populate: 'woocommerce-products-popup', pagination: 'woocommerce-get-products' };
                    case 'shopify':
                        return { area: SBCloud.shopify_products_box, ul: SBCloud.shopify_products_box_ul, search: 'shopify-get-products', filter: 'shopify-get-products', populate: 'shopify-get-products', pagination: 'shopify-get-products' };
                }
            },

            search: function (input, app_name) {
                let app_info = this.getAppInfo(app_name);
                searchInput(input, (search, icon) => {
                    if (search) {
                        this.pagination_reference = 1;
                        SBF.ajax({
                            function: app_info.search,
                            search: search
                        }, (response) => {
                            if (app_name == 'shopify') {
                                this.pagination_reference = response[1];
                                response = response[0];
                            }
                            this.getAppInfo(app_name).ul.html(this.code(response, app_name));
                            $(icon).sbLoading(false);
                        });
                    } else {
                        this.populate(app_name, function () {
                            $(icon).sbLoading(false);
                        });
                    }
                });
            },

            filter: function (item, app_name) {
                let app_info = this.getAppInfo(app_name);
                let value = $(item).data('value');
                if (loading(app_info.ul)) return;
                app_info.ul.html('');
                this.pagination_reference = 1;
                SBF.ajax({
                    function: app_info.filter,
                    user_language: this.panel_language,
                    filters: { taxonomy: value },
                    collection: value
                }, (response) => {
                    if (app_name == 'shopify') {
                        this.pagination_reference = response[1];
                        response = response[0];
                    }
                    app_info.ul.html(this.code(response, app_name)).sbLoading(false);
                });
            },

            populate: function (app_name, onSuccess = false) {
                let app_info = this.getAppInfo(app_name);
                this.panel_language = activeUser() && SB_ADMIN_SETTINGS.languages && SB_ADMIN_SETTINGS.languages.includes(activeUser().language) ? activeUser().language : '';
                this.pagination_reference = 1;
                app_info.ul.html('').sbLoading(true);
                SBF.ajax({
                    function: app_info.populate,
                    user_language: this.panel_language
                }, (response) => {
                    let code = '';
                    let select = app_info.area.find('.sb-select');
                    for (var i = 0; i < response[1].length; i++) {
                        code += `<li data-value="${response[1][i].id}">${response[1][i].name}</li>`;
                    }
                    if (response[2]) {
                        this.pagination_reference = response[2];
                    }
                    if (response[3]) {
                        SB_ADMIN_SETTINGS.currency = response[3];
                    }
                    select.find('> p').html(sb_('All'));
                    select.find('ul').html(`<li data-value="" class="sb-active">${sb_('All')}</li>` + code);
                    app_info.ul.html(this.code(response[0], app_name)).sbLoading(false);
                    if (onSuccess !== false) {
                        onSuccess();
                    }
                });
            },

            pagination: function (area, app_name) {
                let app_info = this.getAppInfo(app_name);
                let filter = $(area).parent().find('.sb-select p').attr('data-value');
                if (!this.pagination_reference) return;
                app_info.ul.sbLoading(area);
                SBF.ajax({
                    function: app_info.pagination,
                    filters: { taxonomy: filter },
                    collection: filter,
                    pagination: this.pagination_reference,
                    user_language: this.panel_language
                }, (response) => {
                    if (app_name == 'shopify') {
                        this.pagination_reference = response[1];
                        response = response[0];
                    } else {
                        this.pagination_reference++;
                    }
                    app_info.ul.append(this.code(response, app_name, false)).sbLoading(false);
                    if (!response.length) {
                        this.pagination_reference = 0;
                    }
                });
            }
        }
    }

    /*
    * ----------------------------------------------------------
    * Settings
    * ----------------------------------------------------------
    */

    var SBSettings = {
        init: false,

        save: function (btn = false) {
            if (btn && loading(btn)) return;
            let external_settings = {};
            let settings = {};
            let tab = settings_area.find(' > .sb-tab > .sb-nav .sb-active').attr('id');
            switch (tab) {
                case 'tab-automations':
                    let active = automations_area_nav.find('.sb-active').attr('data-id');
                    SBSettings.automations.save((response) => {
                        infoBottom(response === true ? 'Automations saved' : response);
                        SBSettings.automations.populate();
                        automations_area_nav.find(`[data-id="${active}"]`).click();
                        if (btn) {
                            $(btn).sbLoading(false);
                        }
                    });
                    break;
                case 'tab-translations':
                    this.translations.updateActive();
                    SBF.ajax({
                        function: 'save-translations',
                        translations: JSON.stringify(this.translations.to_update)
                    }, () => {
                        infoBottom('Translations saved');
                        if (btn) {
                            $(btn).sbLoading(false);
                        }
                    });
                    break;
                default:
                    settings_area.find('.sb-setting').each((i, element) => {
                        let setting = this.get(element);
                        let setting_id = $(element).data('setting');
                        if (setting[0]) {
                            if (typeof setting_id != ND) {
                                let originals = false;
                                if ($(element).find('[data-language]').length) {
                                    let language = $(element).find('[data-language].sb-active');
                                    originals = setting[0] in this.translations.originals ? this.translations.originals[setting[0]] : false;
                                    this.translations.save(element, language.length ? language.attr('data-language') : false);
                                    if (originals) {
                                        if (typeof originals != 'string') {
                                            for (var key in originals) {
                                                originals[key] = [originals[key], setting[1][key][1]]
                                            }
                                        }
                                    }
                                }
                                if (!(setting_id in external_settings)) external_settings[setting_id] = {};
                                external_settings[setting_id][setting[0]] = [originals ? originals : setting[1], setting[2]];
                            } else {
                                settings[setting[0]] = [setting[1], setting[2]];
                            }
                        }
                    });
                    if (!settings['timetable-utc'][0]) {
                        settings['timetable-utc'][0] = (today.getTimezoneOffset() / 60) + '|' + Intl.DateTimeFormat().resolvedOptions().timeZone;
                    }
                    SBF.ajax({
                        function: 'save-settings',
                        settings: JSON.stringify(settings),
                        external_settings: external_settings,
                        external_settings_translations: this.translations.translations
                    }, () => {
                        if (btn) {
                            infoBottom('Settings saved. Reload to apply the changes.');
                            $(btn).sbLoading(false);
                        }
                        SBF.event('SBSettingsSaved', { settings: settings, external_settings: external_settings, external_settings_translations: this.translations.translations });
                    });
                    break;
            }
        },

        get: function (item) {
            item = $(item);
            let id = item.attr('id');
            let type = item.data('type');
            let value;
            switch (type) {
                case 'upload':
                case 'range':
                case 'number':
                case 'text':
                case 'password':
                case 'color':
                case 'upload-file':
                    return [id, item.find('input').val(), type];
                case 'textarea':
                    return [id, item.find('textarea').val(), type];
                case 'select':
                    return [id, item.find('select').val(), type];
                case 'select-ajax':
                    value = item.find('input').attr('data-value');
                    return [id, [value ? value : '', item.find('input').val()], type];
                case 'select-checkbox':
                    return [id, [item.find('.sb-select-checkbox-input').val(), item.find('.sb-select-checkbox-input').attr('data-value')], type];
                case 'checkbox':
                    return [id, item.find('input').is(':checked'), type];
                case 'radio':
                    value = item.find('input:checked').val();
                    if (SBF.null(value)) {
                        value = '';
                    }
                    return [id, value, type];
                case 'upload-image':
                    let url = item.find('.image').attr('data-value');
                    if (SBF.null(url)) {
                        url = '';
                    }
                    return [id, url, type];
                case 'multi-input':
                    let multi_inputs = {};
                    item.find('.input > div').each((i, element) => {
                        let setting = this.get(element);
                        if (setting[0]) {
                            multi_inputs[setting[0]] = [setting[1], setting[2]];
                        }
                    });
                    return [id, multi_inputs, type];
                case 'select-images':
                    return [id, item.find('.input > .sb-active').data('value'), type];
                case 'repeater':
                    return [id, this.repeater.get(item.find('.repeater-item')), type];
                case 'timetable':
                    let times = {};
                    item.find('.sb-timetable > [data-day]').each(function () {
                        let day = $(this).attr('data-day');
                        let hours = [];
                        $(this).find('> div > div').each(function () {
                            let name = $(this).html()
                            let value = $(this).attr('data-value');
                            if (SBF.null(value)) {
                                hours.push(['', 'Closed']);
                            } else if (value == 'closed') { // Deprecated
                                hours.push(['closed', 'Closed']);  // Deprecated
                            } else {
                                hours.push([value, name]);
                            }
                        });
                        times[day] = hours;
                    });
                    return [id, times, type];
                case 'color-palette':
                    return [id, item.attr('data-value'), type];
            }
            return ['', '', ''];
        },

        set: function (id, setting) {
            let type = $(setting)[1];
            let value = $(setting)[0];
            id = `#${id}`;
            switch (type) {
                case 'color':
                case 'upload':
                case 'number':
                case 'text':
                case 'password':
                case 'upload-file':
                    settings_area.find(`${id} input`).val(value);
                    break;
                case 'textarea':
                    settings_area.find(`${id} textarea`).val(value);
                    break;
                case 'select':
                    settings_area.find(`${id} select`).val(value);
                    break;
                case 'select-ajax':
                    settings_area.find(`${id} input`).attr('data-value', value[0]).val(value[1]);
                    break;
                case 'select-checkbox':
                    let values = value && value[0] ? value[0].split(',') : [];
                    values.forEach((value_) => {
                        settings_area.find(`input[id="${value_.replace(/ /g, '')}"]`).prop('checked', true);
                    });
                    settings_area.find(id + ' .sb-select-checkbox-input').attr('data-value', value[0]).val(value[1]);
                    break;
                case 'checkbox':
                    settings_area.find(`${id} input`).prop('checked', value == 'false' ? false : value);
                    break;
                case 'radio':
                    settings_area.find(`${id} input[value="${value}"]`).prop('checked', true);
                    break;
                case 'upload-image':
                    if (value) {
                        settings_area.find(id + ' .image').attr('data-value', value).css('background-image', `url("${value}")`);
                    }
                    break;
                case 'multi-input':
                    for (var key in value) {
                        this.set(key, value[key]);
                    }
                    break;
                case 'range':
                    let range_value = value;
                    settings_area.find(id + ' input').val(range_value);
                    settings_area.find(id + ' .range-value').html(range_value);
                    break;
                case 'select-images':
                    settings_area.find(id + ' .input > div').sbActive(false);
                    settings_area.find(id + ` .input > [data-value="${value}"]`).sbActive(true);
                    break;
                case 'repeater':
                    let content = this.repeater.set(value, settings_area.find(id + ' .repeater-item:last-child'));
                    if (content) {
                        settings_area.find(id + ' .sb-repeater').html(content);
                    }
                    break;
                case 'timetable':
                    for (var key in value) {
                        let hours = settings_area.find(`${id} [data-day="${key}"] > div > div`);
                        for (var i = 0; i < hours.length; i++) {
                            $(hours[i]).attr('data-value', value[key][i][0]).html(value[key][i][1]);
                        }
                    }
                    break;
                case 'color-palette':
                    if (value) {
                        settings_area.find(id).attr('data-value', value);
                    }
                    break;
            }
        },

        repeater: {
            set: function (values, repeater_item_content) {
                var html = '';
                this.clear($(repeater_item_content));
                repeater_item_content = $(repeater_item_content).html();
                if (values.length) {
                    $(repeater_item_content).find('> .sb-icon-close').remove();
                    for (var i = 0; i < values.length; i++) {
                        let item = $($.parseHTML(`<div>${repeater_item_content}</div>`));
                        for (var key in values[i]) {
                            SBSettings.input.set(item.find(`[data-id="${key}"]`), values[i][key]);
                        }
                        html += `<div class="repeater-item">${item.html().replaceAll('<i class="sb-icon-close"></i>', '')}<i class="sb-icon-close"></i></div>`;
                    }
                }
                return html;
            },

            get: function (items) {
                let items_array = [];
                $(items).each(function () {
                    let item = {};
                    let empty = true;
                    $(this).find('[data-id]').removeClass('sb-exclude');
                    $(this).find('.sb-repeater [data-id]').addClass('sb-exclude');
                    $(this).find('[data-id]:not(.sb-exclude)').each(function () {
                        let value = SBSettings.input.get(this);
                        if (empty && value && $(this).attr('type') != 'hidden' && $(this).attr('data-type') != 'auto-id') {
                            empty = false;
                        }
                        item[$(this).attr('data-id')] = value;
                    });
                    if (!empty) {
                        items_array.push(item);
                    }
                });
                return items_array;
            },

            add: function (item) {
                let parent = $(item).parent();
                item = $($.parseHTML(`<div>${parent.find('> .sb-repeater > .repeater-item:last-child').html()}</div>`));
                this.clear(item);
                item.find('.repeater-item:not(:first-child)').remove();
                item.find('[data-id]').each(function () {
                    SBSettings.input.reset(this);
                    if ($(this).data('type') == 'auto-id') {
                        let larger = 1;
                        parent.find('[data-type="auto-id"]').each(function () {
                            let index = parseInt($(this).val());
                            if (index > larger) {
                                larger = index;
                            }
                        });
                        $(this).attr('value', larger + 1);
                    }
                });
                parent.find('> .sb-repeater').append(`<div class="repeater-item">${item.html()}</div>`);
            },

            delete: function (item) {
                let parent = $(item).parent();
                let cnt = parent.parent();
                if (cnt.parent().find('.sb-repeater-upload').length) {
                    SBF.ajax({ function: 'delete-file', path: parent.find('input').val() });
                }
                if (cnt.find('> .repeater-item').length > 1) {
                    parent.remove();
                } else {
                    parent.find('[data-id]:not([data-type="auto-id"]').each((e, element) => {
                        SBSettings.input.reset(element);
                    });
                }
            },

            clear: function (item) {
                item.find('.sb-active').sbActive(false);
                item.find('input:not([data-type="auto-id"]').removeAttr('value checked');
                item.find('option').removeAttr('selected');
                item.find('.sb-hide').removeClass('sb-hide');
            }
        },

        input: {
            set: function (input, value) {
                input = $(input);
                if (typeof value != 'object') {
                    value = $.trim(value);
                }
                if (input.is('select')) {
                    input.find(`option[value="${value}"]`).attr('selected', '');
                } else if (input.is(':checkbox') && value && value != 'false') {
                    input.attr('checked', '');
                } else if (input.is('textarea')) {
                    input.html(value);
                } else {
                    let div = input.is('div');
                    if (input.hasClass('sb-repeater')) {
                        input.html(SBSettings.repeater.set(value, '<div>' + input.find('> .repeater-item').eq(0).html() + '</div>').replaceAll('sb-icon-close', 'sb-icon-close sb-sub-repeater-close'));
                    } else if (input.attr('data-type') == 'select-ajax') {
                        input.attr('data-value', value[0]).attr('value', typeof value[1] === ND ? value[0] : value[1]); // Deprecated. Replace  typeof value[1] === ND ? value[0] : value[1] with: value[1] 
                    } else if (input.attr('data-type') == 'select-checkbox') {
                        input.attr('data-value', value[0]).attr('value', value[1]);
                    } else if (div || input.is('i') || input.is('li')) {
                        input.attr('data-value', value);
                        if (div && input.hasClass('image')) {
                            input.css('background-image', value ? `url("${value}")` : '');
                        }
                    } else {
                        input.attr('value', value);
                    }
                }
            },

            get: function (input) {
                input = $(input);
                if (input.is(':checkbox')) {
                    return input.is(':checked');
                } else if (input.hasClass('sb-repeater')) {
                    return SBSettings.repeater.get(input.find('> .repeater-item'));
                } else if (input.attr('data-type') == 'select-ajax') {
                    return [input.attr('data-value'), input.val()];
                } else if (input.attr('data-type') == 'select-checkbox') {
                    return [input.attr('data-value'), input.val()];
                } else if (input.is('div') || input.is('i') || input.is('li')) {
                    let value = input.attr('data-value');
                    return value ? value : '';
                } else {
                    return input.val();
                }
                return '';
            },

            reset: function (input) {
                input = $(input);
                if (input.is('select')) {
                    input.val('').find('[selected]').removeAttr('selected');
                } else if (input.is(':checkbox')) {
                    input.removeAttr('checked').prop('checked', false);
                } else if (input.is('textarea')) {
                    input.val('');
                    input.html('');
                } else if (input.hasClass('sb-repeater')) {
                    input.find('.repeater-item:not(:first-child)').remove();
                } else {
                    input.removeAttr('value style data-value').val('');
                }
            }
        },

        initColorPicker: function (area = false) {
            $(area ? area : settings_area).find('.sb-type-color input').colorPicker({
                renderCallback: function (t, toggled) {
                    $(t.context).closest('.input').find('input').css('background-color', t.text);
                }
            });
        },

        loadDatePicker: function (onSuccess) {
            if (typeof $.fn.daterangepicker === ND) {
                $.getScript(SB_URL + '/vendor/moment.min.js', () => {
                    $.getScript(SB_URL + '/vendor/daterangepicker.min.js', () => {
                        onSuccess();
                    });
                });
            } else {
                onSuccess();
            }
        },

        getDatePickerSettings: function (is_single = false, is_future_only = false, is_past_only = false) {
            let settings = {
                ranges: {},
                locale: {
                    format: 'DD/MM/YYYY',
                    separator: ' - ',
                    applyLabel: sb_('Apply'),
                    cancelLabel: sb_('Cancel'),
                    fromLabel: sb_('From'),
                    toLabel: sb_('To'),
                    customRangeLabel: sb_('Custom'),
                    weekLabel: sb_('W'),
                    daysOfWeek: [
                        sb_('Su'),
                        sb_('Mo'),
                        sb_('Tu'),
                        sb_('We'),
                        sb_('Th'),
                        sb_('Fr'),
                        sb_('Sa')
                    ],
                    monthNames: [
                        sb_('January'),
                        sb_('February'),
                        sb_('March'),
                        sb_('April'),
                        sb_('May'),
                        sb_('June'),
                        sb_('July'),
                        sb_('August'),
                        sb_('September'),
                        sb_('October'),
                        sb_('November'),
                        sb_('December')
                    ],
                    firstDay: 1
                },
                showCustomRangeLabel: !is_single,
                alwaysShowCalendars: true,
                autoApply: true,
                opens: admin.hasClass('sb-rtl') ? 'left' : 'right'
            };
            if (is_single) {
                settings.singleDatePicker = true;
            } else {
                settings.ranges[sb_('Today')] = [moment(), moment()];
                settings.ranges[sb_('Yesterday')] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
                settings.ranges[sb_('Last 7 Days')] = [moment().subtract(6, 'days'), moment()];
                settings.ranges[sb_('Last 30 Days')] = [moment().subtract(29, 'days'), moment()];
                settings.ranges[sb_('This Month')] = [moment().startOf('month'), moment().endOf('month')];
                settings.ranges[sb_('Last Month')] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
            }
            if (is_future_only) {
                settings.minDate = moment();
            }
            if (is_past_only) {
                settings.maxDate = moment();
            }
            return settings;
        },

        getSettingObject: function (setting) {
            return $(setting)[0].hasAttribute('data-setting') ? $(setting) : $(setting).closest('[data-setting]');
        },

        visibility: function (index, visible) {
            let selectors = [
                ['#push-notifications-onesignal-sw-url, #push-notifications-onesignal-app-id, #push-notifications-onesignal-api-key, #push-notifications-sw-path', '#push-notifications-id, #push-notifications-key'],
                ['#messenger-key, #messenger-path-btn', '#messenger-sync-btn'],
                ['#open-ai-assistant-id', '#open-ai-prompt,#open-ai-model, #open-ai-tokens, #open-ai-temperature, #open-ai-presence-penalty, #open-ai-frequency-penalty, #open-ai-logit-bias, #open-ai-custom-model, #open-ai-source-links'],
                [false, '#header-exclude-admins']
            ];
            if (selectors[index][0]) {
                settings_area.find(selectors[index][0]).sbActive(!visible);
            }
            settings_area.find(selectors[index][0]).sbActive(!visible);
            settings_area.find(selectors[index][1]).setClass('sb-hide', !visible);
        },

        open: function (id, scroll = false) {
            header.find('#sb-settings').click();
            if (scroll) {
                setTimeout(() => {
                    settings_area.find('#tab-' + id).click().get(0).scrollIntoView();
                }, 300);
            }
        },

        automations: {
            items: { messages: [], emails: [], sms: [], popups: [], design: [], more: [] },
            translations: {},

            conditions: function () {
                let list = {
                    datetime: ['Date time', ['Is between', 'Is exactly'], 'dd/mm/yyyy hh:mm - dd/mm/yyyy hh:mm'],
                    repeat: ['Repeat', ['Every day', 'Every week', 'Every month', 'Every year']],
                    browsing_time: ['Browsing time', [], 'seconds'],
                    scroll_position: ['Scroll position', [], 'px'],
                    url: ['Current URL', ['Contains', 'Does not contain'], 'URLs parts separated by commas'],
                    referring: ['Referring URL', ['Contains', 'Does not contain'], 'URLs parts separated by commas'],
                    user_type: ['User type', ['Is visitor', 'Is lead', 'Is user', 'Is not visitor', 'Is not lead', 'Is not user']],
                    returning_visitor: ['Returning visitor', ['First time visitor', 'Returning visitor']],
                    countries: ['Country', ['Is included', 'Is not included', 'Is set', 'Is not set'], 'Country codes separated by commas'],
                    languages: ['Language', ['Is included', 'Is not included', 'Is set', 'Is not set'], 'Language codes separated by commas'],
                    cities: ['City', ['Is included', 'Is not included', 'Is set', 'Is not set'], 'Cities separated by commas'],
                    website: ['Website', ['Contains', 'Does not contain', 'Is set', 'Is not set'], 'URLs parts separated by commas'],
                    birthdate: ['Birthdate', ['Is between', 'Is exactly', 'Is set', 'Is not set'], 'dd/mm - dd/mm'],
                    company: ['Company', ['Is included', 'Is not included', 'Is set', 'Is not set'], 'Company names separated by commas'],
                    postal_code: ['Postal code', ['Is included', 'Is not included', 'Is set', 'Is not set'], 'Postal codes separated by commas'],
                    email: ['Email', ['Contains', 'Does not contain', 'Is set', 'Is not set'], 'Email addresses separated by commas'],
                    phone: ['Phone', ['Contains', 'Does not contain', 'Is set', 'Is not set'], 'Phone numbers separated by commas'],
                    creation_time: ['Creation time', ['Is between', 'Is exactly'], 'dd/mm/yyyy hh:mm - dd/mm/yyyy hh:mm'],
                    custom_variable: ['Custom variable', [], 'variable=value']
                };
                let user_extra_details = SBUsers.getExtraDetailsList(true);
                for (var i = 0; i < user_extra_details.length; i++) {
                    list[user_extra_details[i][0]] = [user_extra_details[i][1], ['Contains', 'Does not contain', 'Is set', 'Is not set'], 'Values separated by commas'];
                }
                return list;
            },

            get: function (onSuccess) {
                SBF.ajax({
                    function: 'automations-get'
                }, (response) => {
                    this.items = response[0];
                    this.translations = Array.isArray(response[1]) && !response[1].length ? {} : response[1];
                    onSuccess(response);
                });
            },

            save: function (onSuccess = false) {
                this.updateActiveItem();
                SBF.ajax({
                    function: 'automations-save',
                    automations: this.items,
                    translations: this.translations
                }, (response) => {
                    if (onSuccess) onSuccess(response);
                });
            },

            show: function (id = false, language = false) {
                this.updateActiveItem();
                let items = language ? (language in this.translations ? this.translations[language] : []) : this.items;
                let area = automations_area.find(' > .sb-tab > .sb-content');
                if (id === false) id = this.activeID();
                this.hide(false);
                for (var key in items) {
                    for (var i = 0; i < items[key].length; i++) {
                        let item = items[key][i];
                        if (item.id == id) {
                            for (var key in item) {
                                let element = area.find(`[data-id="${key}"]`);
                                if (element.hasClass('image')) {
                                    element.css('background-image', `url(${item[key]})`).attr('data-value', item[key]);
                                    if (!item[key]) {
                                        element.removeAttr('data-value');
                                    }
                                } else if (element.attr('type') == 'checkbox') {
                                    element.prop('checked', item[key]);
                                } else {
                                    element.val(item[key]);
                                }
                            }
                            this.setConditions(item.conditions, conditions_area);
                            conditions_area.parent().setClass('sb-hide', language);
                            area.sbLanguageSwitcher(this.getTranslations(id), 'automations', language);
                            return true;
                        }
                    }
                }
                return false;
            },

            add: function () {
                let id = SBF.random();
                let name = `${sb_('Item')} ${automations_area_nav.find('li:not(.sb-no-results)').length + 1}`;
                this.updateActiveItem();
                this.items[this.activeType()].push(this.itemArray(this.activeType(), id, name));
                this.hide(false);
                automations_area_nav.find('.sb-active').sbActive(false);
                automations_area_nav.find('.sb-no-results').remove();
                automations_area_nav.append(`<li class="sb-active" data-id="${id}">${name}<i class="sb-icon-delete"></i></li>`);
                automations_area.find('.sb-automation-values').find('input, textarea').val('');
                automations_area.sbLanguageSwitcher([], 'automations');
                conditions_area.html('');
            },

            delete: function (element) {
                this.items[this.activeType()].splice($(element).parent().index(), 1);
                $(element).parent().remove();
                this.hide();
                if (this.items[this.activeType()].length == 0) automations_area_nav.html(`<li class="sb-no-results">${sb_('No results found.')}</li>`);
            },

            populate: function (type = false) {
                if (type === false) {
                    type = this.activeType();
                }
                let code = '';
                let items = this.items[type];
                this.updateActiveItem();
                if (items.length) {
                    for (var i = 0; i < items.length; i++) {
                        code += `<li data-id="${items[i].id}">${items[i].name}<i class="sb-icon-delete"></i></li>`;
                    }
                } else {
                    code = `<li class="sb-no-results">${sb_('No results found.')}</li>`;
                }
                automations_area_nav.html(code);
                code = '';
                switch (type) {
                    case 'emails':
                        code = `<h2>${sb_('Subject')}</h2><div class="sb-setting sb-type-text"><div><input data-id="subject" type="text"></div></div>`;
                        break;
                    case 'popups':
                        code = `<h2>${sb_('Title')}</h2><div class="sb-setting sb-type-text"><div><input data-id="title" type="text"></div></div><h2>${sb_('Profile image')}</h2><div data-type="upload-image" class="sb-setting sb-type-upload-image"><div class="input"><div data-id="profile_image" class="image"><i class="sb-icon-close"></i></div></div></div><h2>${sb_('Message fallback')}</h2><div class="sb-setting sb-type-checkbox"><div><input data-id="fallback" type="checkbox"></div></div>`;
                        break;
                    case 'design':
                        code = `<h2>${sb_('Header title')}</h2><div class="sb-setting sb-type-text"><div><input data-id="title" type="text"></div></div>`;
                        for (var i = 1; i < 4; i++) {
                            code += `<h2>${sb_((i == 1 ? 'Primary' : (i == 2 ? 'Secondary' : 'Tertiary')) + ' color')}</h2><div data-type="color" class="sb-setting sb-type-color"><div class="input"><input data-id="color_${i}" type="text"><i class="sb-close sb-icon-close"></i></div></div>`;
                        }
                        for (var i = 1; i < 4; i++) {
                            code += `<h2>${sb_(i == 1 ? 'Header background image' : (i == 2 ? 'Header brand image' : 'Chat button icon'))}</h2><div data-type="upload-image" class="sb-setting sb-type-upload-image"><div class="input"><div data-id="${i == 1 ? 'background' : (i == 2 ? 'brand' : 'icon')}" class="image"><i class="sb-icon-close"></i></div></div></div>`;
                        }
                        break;
                    case 'more':
                        code = `<h2>${sb_('Department ID')}</h2><div class="sb-setting sb-type-number"><div><input data-id="department" type="number"></div></div><h2>${sb_('Agent ID')}</h2><div class="sb-setting sb-type-number"><div><input data-id="agent" type="number"></div></div><h2>${sb_('Tags')}</h2><div class="sb-setting sb-type-text"><div><input data-id="tags" type="text"></div></div><h2>${sb_('Article IDs')}</h2><div class="sb-setting sb-type-number"><div><input data-id="articles" type="text"></div></div><h2>${sb_('Articles category')}</h2><div class="sb-setting sb-type-number"><div><input data-id="articles_category" type="text"></div></div>`;
                        break;
                }
                automations_area.find('.sb-automation-extra').html(code);
                automations_area.attr('data-automation-type', type);
                SBSettings.initColorPicker(automations_area);
                this.hide();
            },

            updateActiveItem: function () {
                let id = this.activeID();
                if (id) {
                    let language = automations_area.find(`.sb-language-switcher [data-language].sb-active`).attr('data-language');
                    let type = this.activeType();
                    let items = language ? (language in this.translations ? this.translations[language][type] : []) : this.items[type];
                    for (var i = 0; i < items.length; i++) {
                        if (items[i].id == id) {
                            items[i] = { id: id, conditions: [] };
                            automations_area.find('.sb-automation-values').find('input,textarea,[data-type="upload-image"] .image').each(function () {
                                items[i][$(this).attr('data-id')] = $(this).hasClass('image') && $(this)[0].hasAttribute('data-value') ? $(this).attr('data-value') : ($(this).attr('type') == 'checkbox' ? $(this).is(':checked') : $(this).val());
                            });
                            items[i].conditions = this.getConditions(conditions_area);
                            if (SBF.null(items[i].name)) {
                                this.delete(automations_area_nav.find(`[data-id="${id}"] i`));
                            }
                            break;
                        }
                    }
                }
            },

            getConditions: function (conditions_area) {
                let conditions = [];
                conditions_area.find(' > div').each(function () {
                    let condition = [];
                    $(this).find('input,select').each(function () {
                        condition.push($(this).val());
                    });
                    if (condition[0] && condition[1] && (condition.length == 2 || condition[2] || ['is-set', 'is-not-set'].includes(condition[1]))) {
                        conditions.push(condition);
                    }
                });
                return conditions;
            },

            setConditions: function (conditions, conditions_area) {
                conditions_area.html('');
                if (conditions) {
                    for (var key in conditions) {
                        this.addCondition(conditions_area);
                        let condition = conditions_area.find(' > div:last-child');
                        condition.find('select').val(conditions[key][0]);
                        this.updateCondition(condition.find('select'));
                        condition.find(' > div').eq(1).find('select,input').val(conditions[key][1]);
                        if (conditions[key].length > 2) {
                            if (['is-set', 'is-not-set'].includes(conditions[key][1])) {
                                condition.find(' > div').eq(2).addClass('sb-hide');
                            } else {
                                condition.find(' > div').eq(2).find('input').val(conditions[key][2]);
                            }
                        }
                    }
                }
            },

            addCondition: function (conditions_area) {
                conditions_area.append(`<div><div class="sb-setting sb-type-select sb-condition-1"><select>${this.getAvailableConditions()}</select></div></div>`);
            },

            updateCondition: function (element) {
                $(element).parent().siblings().remove();
                let parent = $(element).parents().eq(1);
                if ($(element).val()) {
                    let condition = this.conditions()[$(element).val()];
                    let code = '';
                    if (condition[1].length) {
                        code = '<div class="sb-setting sb-type-select sb-condition-2"><select>';
                        for (var i = 0; i < condition[1].length; i++) {
                            code += `<option value="${SBF.stringToSlug(condition[1][i])}">${sb_(condition[1][i])}</option>`;
                        }
                        code += '</select></div>';
                    }
                    parent.append(code + (condition.length > 2 ? `<div class="sb-setting sb-type-text"><input placeholder="${sb_(condition[2])}" type="text"></div>` : ''));
                    parent.siblings().find('.sb-condition-1 select').each(function () {
                        let value = $(this).val();
                        $(this).html(SBSettings.automations.getAvailableConditions([value]));
                        $(this).val(value);
                    });
                } else {
                    parent.remove();
                }
            },

            getAvailableConditions: function (include = [], exclude = []) {
                let code = '<option value=""></option>';
                let existing_conditions = [];
                let conditions = this.conditions();
                conditions_area.find('.sb-condition-1 select').each(function () {
                    existing_conditions.push($(this).val());
                });
                for (var key in conditions) {
                    if (!exclude.includes(key) && (!existing_conditions.includes(key) || include.includes(key))) {
                        code += `<option value="${key}">${sb_(conditions[key][0])}</option>`;
                    }
                }
                return code;
            },

            addTranslation: function (id = false, type = false, language) {
                if (id === false) {
                    id = this.activeID();
                }
                if (type === false) {
                    type = this.activeType();
                }
                if (this.getTranslations(id).includes(id)) {
                    return console.warn('Automation translation already in array.');
                }
                if (!(language in this.translations)) {
                    this.translations[language] = { messages: [], emails: [], sms: [], popups: [], design: [] };
                }
                if (!(type in this.translations[language])) {
                    this.translations[language][type] = [];
                }
                this.translations[language][type].push(this.itemArray(type, id));
            },

            getTranslations: function (id = false) {
                let translations = [];
                if (id === false) id = this.activeID();
                for (var key in this.translations) {
                    let types = this.translations[key];
                    for (var key2 in types) {
                        let items = types[key2];
                        for (var i = 0; i < items.length; i++) {
                            if (items[i].id == id) {
                                translations.push(key);
                                break;
                            }
                        }
                    }
                }
                return translations;
            },

            deleteTranslation: function (id = false, language) {
                if (id === false) id = this.activeID();
                if (language in this.translations) {
                    let types = this.translations[language];
                    for (var key in types) {
                        let items = types[key];
                        for (var i = 0; i < items.length; i++) {
                            if (items[i].id == id) {
                                this.translations[language][key].splice(i, 1);
                                return true;
                            }
                        }
                    }
                }
                return false;
            },

            activeID: function () {
                let item = automations_area_nav.find('.sb-active');
                return item.length ? item.attr('data-id') : false;
            },

            activeType: function () {
                return automations_area_select.find('li.sb-active').data('value');
            },

            itemArray: function (type, id, name = '', message = '') {
                return $.extend({ id: id, name: name, message: message }, type == 'emails' ? { subject: '' } : (type == 'popups' ? { title: '', profile_image: '' } : (type == 'design' ? { title: '', color_1: '', color_2: '', color_3: '', background: '', brand: '', icon: '' } : {})));
            },

            hide: function (hide = true) {
                automations_area.find(' > .sb-tab > .sb-content').setClass('sb-hide', hide);
            }
        },

        translations: {
            translations: {},
            originals: {},
            to_update: {},

            add: function (language) {
                let setting = SBSettings.getSettingObject(language_switcher_target);
                let setting_id = setting.attr('id');
                let active_language = language_switcher_target.find('[data-language].sb-active');
                this.save(setting, active_language.length ? active_language.attr('data-language') : false);
                setting.find('textarea,input[type="text"]').val('');
                this.save(setting, language);
                language_switcher_target.remove();
                setting.sbLanguageSwitcher(this.getLanguageCodes(setting_id), 'settings', language);
            },

            delete: function (setting, language) {
                setting = SBSettings.getSettingObject(setting);
                let setting_id = setting.attr('id');
                delete this.translations[language][setting_id];
                setting.find(`.sb-language-switcher [data-language="${language}"]`).remove();
                this.activate(setting);
            },

            activate: function (setting, language = false) {
                setting = SBSettings.getSettingObject(setting);
                let setting_id = setting.attr('id');
                let values = language ? this.translations[language][setting_id] : this.originals[setting_id];
                if (isString(values)) {
                    setting.find('input, textarea').val(values);
                } else {
                    for (var key in values) {
                        setting.find('#' + key).find('input, textarea').val(isString(values[key]) ? values[key] : values[key][0]);
                    }
                }
            },

            updateActive: function () {
                let area = settings_area.find('.sb-translations-list')
                let translations = { front: {}, admin: {}, 'admin/js': {}, 'admin/settings': {} };
                let language_code = area.attr('data-value');
                if (SBF.null(language_code)) return;
                for (var key in translations) {
                    area.find(' > [data-area="' + key + '"] .sb-setting:not(.sb-new-translation)').each(function () {
                        translations[key][$(this).find('label').html()] = $(this).find('input').val();
                    });
                    area.find('> [data-area="' + key + '"] .sb-new-translation').each(function () {
                        let original = $(this).find('input:first-child').val();
                        let value = $(this).find('input:last-child').val();
                        if (original && value) {
                            translations[key][original] = value;
                        }
                    });
                }
                this.to_update[language_code] = translations;
            },

            save: function (setting, language = false) {
                setting = SBSettings.getSettingObject(setting);
                let values = {};
                let setting_id = $(setting).attr('id');
                if (setting.data('type') == 'multi-input') {
                    setting.find('.multi-input-textarea,.multi-input-text').each(function () {
                        values[$(this).attr('id')] = $(this).find('input, textarea').val();
                    });
                } else {
                    values = setting.find('input, textarea').val();
                }
                if (language) {
                    if (!(language in this.translations)) {
                        this.translations[language] = {};
                    }
                    this.translations[language][setting_id] = values;
                } else {
                    this.originals[setting_id] = values;
                }
            },

            load: function (language_code) {
                let area = settings_area.find('.sb-translations > .sb-content');
                area.find(' > .sb-hide').removeClass('sb-hide');
                this.updateActive();
                SBF.ajax({
                    function: 'get-translation',
                    language_code: language_code
                }, (translations) => {
                    if (language_code in this.to_update) translations = this.to_update[language_code];
                    let code = '';
                    let areas = ['front', 'admin', 'admin/js', 'admin/settings'];
                    for (var i = 0; i < areas.length; i++) {
                        let translations_area = translations[areas[i]];
                        code += `<div${!i ? ' class="sb-active"' : ''} data-area="${areas[i]}">`;
                        for (var key in translations_area) {
                            code += `<div class="sb-setting sb-type-text"><label>${key}</label><div><input type="text" value="${translations_area[key]}"></div></div>`;
                        }
                        code += '</div>';
                    }
                    area.find('.sb-translations-list').attr('data-value', language_code).html(code);
                    area.find('.sb-menu-wide li').sbActive(false).eq(0).sbActive(true);
                    area.sbLoading(false);
                });
                area.sbLoading(true);
            },

            getLanguageCodes: function (setting_id) {
                let languages = [];
                for (var key in this.translations) {
                    if (setting_id in this.translations[key]) {
                        languages.push(key);
                    }
                }
                return languages;
            }
        },

        getSelectDepartments: function (active_department_id = false) {
            if (SB_ADMIN_SETTINGS.departments.length) {
                let code = '<select class="sb-select-departments"><option value=""></option>';
                for (let index in SB_ADMIN_SETTINGS.departments) {
                    let department = SB_ADMIN_SETTINGS.departments[index];
                    code += `<option value="${department['department-id']}"${active_department_id && active_department_id == department['department-id'] ? ' selected' : ''}>${department['department-name']}</option>`;
                }
                return code + '</select>'
            }
            return '';
        }
    }

    /*
    * ----------------------------------------------------------
    * Articles
    * ----------------------------------------------------------
    */

    var SBArticles = {
        category_list: [],
        page_url: false,

        get: function (onSuccess, article_id = false, categories = false, full = true, language = false) {
            SBF.ajax({
                function: 'get-articles',
                id: article_id,
                categories: categories,
                articles_language: language,
                full: full
            }, (response) => {
                onSuccess(response);
            });
        },

        save: function (onSuccess = false) {
            let id = this.activeID();
            let article;
            article = { id: id, title: articles_area.find('.sb-article-title input').val(), content: articles_area.find('.sb-article-content textarea').val(), link: articles_area.find('.sb-article-link input').val(), parent_category: articles_category_parent_select.val(), category: articles_category_select.val(), language: articles_area.find('.sb-language-switcher [data-language].sb-active').attr('data-language') };
            if (!article.title && !article.content) {
                return onSuccess(false);
            }
            if (article.language) {
                article.parent_id = this.activeID(true);
            }
            if (editor_js && typeof editor_js.save !== ND) {
                editor_js.save().then((outputData) => {
                    article.editor_js = outputData;
                    article.content = editorJSHTML(outputData.blocks);
                    this.save_2(article, onSuccess);
                }).catch((error) => {
                    console.log(error);
                });
            } else {
                this.save_2(article, onSuccess);
            }
        },

        save_2: function (article, onSuccess = false) {
            SBF.ajax({
                function: 'save-article',
                article: JSON.stringify(article)
            }, (response) => {
                let is_number = response !== true && !isNaN(response);
                articles_save_required = false;
                if (is_number) {
                    articles_content.attr('data-id', response);
                    article.id = response;
                    this.viewButton(response)
                    if (article.language) {
                        let translations = SBArticles.translations.get(article.parent_id);
                        articles_content.find(`.sb-language-switcher [data-language="${article.language}"]`).attr('data-id', response);
                        for (var i = 0; i < translations.length; i++) {
                            if (translations[i][0] == article.language) {
                                translations[i][1] = article.id;
                                SBArticles.translations.list[article.parent_id] = translations;
                                break;
                            }
                        }
                    }
                }
                if (!article.language) {
                    articles_area.find('.ul-articles .sb-active').html(article.title + '<i class="sb-icon-delete"></i>').attr('data-id', article.id);
                }
                if (onSuccess) {
                    onSuccess(response);
                }
                infoBottom(response === true || is_number ? 'Article saved' : response);
            });
        },

        show: function (article_id) {
            if (!article_id) {
                return;
            }
            loading(articles_content);
            this.get((response) => {
                articles_content.sbLoading(false);
                response = response[0];
                articles_content.sbLanguageSwitcher(this.translations.get(response.parent_id ? response.parent_id : article_id), 'articles', response.language);
                articles_content.attr('data-id', article_id);
                articles_area.find('.sb-article-title input').val(response.title);
                articles_area.find('.sb-article-link input').val(response.link);
                articles_area.find('#sb-article-id').html(`ID <span>${article_id}</span>`);
                articles_area.find('.sb-article-categories').setClass('sb-hide', response.language);
                if (editor_js || articles_area.find('#editorjs').length) {
                    editorJSLoad(response.editor_js ? (isString(response.editor_js) ? JSON.parse(response.editor_js) : response.editor_js) : response.content);
                } else {
                    articles_area.find('.sb-article-content textarea').val(response.content);
                }
                if (!response.language) {
                    articles_category_parent_select.val(response.parent_category);
                    articles_category_select.val(response.category);
                }
                this.viewButton(article_id)
                articles_save_required = false;
            }, article_id);
        },

        add: function () {
            let nav = articles_area.find('.ul-articles');
            nav.find('.sb-active').sbActive(false);
            nav.append(`<li class="sb-active"></li>`);
            articles_content.sbLanguageSwitcher([], 'articles');
            this.clear();
        },

        clear: function () {
            articles_content.removeAttr('data-id').removeClass('sb-hide');
            articles_content.find('input, textarea, select').val('');
            articles_content.find('input').prop('checked', false);
            editorJSLoad();
            this.viewButton();
            articles_save_required = false;
        },

        delete: function (article_id, onSuccess = false) {
            SBF.ajax({
                function: 'save-article',
                article: JSON.stringify({ id: article_id, delete: true })
            }, (response) => {
                this.clear();
                if (onSuccess) {
                    onSuccess(response);
                }
            });
        },

        populate: function (items, is_category = false) {
            let code = '';
            for (var i = 0; i < items.length; i++) {
                code += `<li data-id="${items[i].id}">${items[i].title}<i class="sb-icon-delete"></i></li>`;
            }
            articles_area.find(is_category ? '.ul-categories' : '.ul-articles').html(code);
            articles_area.find(is_category ? '.ul-categories > li' : '.ul-articles > li').eq(0).click();
            if (!items.length) {
                $(is_category ? articles_content_categories : articles_content).sbLoading(false).addClass('sb-hide');
            }
        },

        activeID: function (is_parent = false) {
            return is_parent ? articles_area.find('.ul-articles .sb-active').attr('data-id') : articles_content.attr('data-id');
        },

        viewButton: function (article_id = false) {
            if (this.page_url) {
                let button = articles_area.find('.sb-view-article');
                button.attr('href', article_id ? this.page_url + (this.is_url_rewrite ? (this.page_url.charAt(this.page_url.length - 1) == '/' ? '' : '/') + (this.cloud_chat_id ? this.cloud_chat_id + '/' : '') : '?article_id=') + article_id : '');
            }
        },

        categories: {
            list: [],

            save: function (onSuccess = false) {
                this.updateActive();
                SBF.ajax({
                    function: 'save-articles-categories',
                    categories: JSON.stringify(this.list)
                }, (response) => {
                    if (onSuccess) {
                        onSuccess(response);
                    }
                    infoBottom(response === true ? 'Categories saved' : response);
                })
            },

            show: function (category_id, language = false) {
                let index = this.getIndex(category_id);
                if (index !== false) {
                    let category = language ? this.list[index].languages[language] : this.list[index];
                    let image = articles_content_categories.find('#category-image');
                    this.updateActive();
                    articles_content_categories.find('#category-title').val(category.title);
                    articles_content_categories.find('#category-description').val(category.description);
                    articles_content_categories.find('#category-parent').prop('checked', category.parent ? true : false);
                    articles_content_categories.sbLanguageSwitcher($.map(this.list[index].languages, function (e, index) { return index }), 'article-categories', language);
                    if (category.image) {
                        image.attr('data-value', category.image).css('background-image', `url("${category.image}")`);
                    } else {
                        image.removeAttr('data-value style');
                    }
                    articles_content_categories.find('.category-parent').setClass('sb-hide', language);
                }
                articles_content_categories.sbLoading(false);
            },

            add: function () {
                let category_id = SBF.random();
                this.list.push({ id: category_id, title: '', description: '', image: '', languages: [] });
                let code = `<li data-id="${category_id}">${sb_('New category')}<i class="sb-icon-delete"></i></li>`;
                articles_area.find('.ul-categories').append(code);
                articles_area.find('.ul-categories li').eq(articles_area.find('.ul-categories li').length - 1).click();
                articles_content_categories.removeClass('sb-hide');
            },

            delete: function (category_id) {
                let index = this.getIndex(category_id);
                let ul = articles_area.find('.ul-categories');
                if (index !== false) {
                    this.list.splice(index, 1);
                    ul.find(`[data-id="${category_id}"]`).remove();
                    ul.find('li').eq(0).click();
                    return true;
                }
                return false;
            },

            update: function () {
                let selected_category = articles_category_select.val();
                let selected_category_parent = articles_category_parent_select.val();
                let code = ['', '<option></option>'];
                let ids = this.list.map(function (item) {
                    return item.id;
                });
                for (var i = 0; i < this.list.length; i++) {
                    code[this.list[i].parent ? 0 : 1] += `<option value="${this.list[i].id}">${this.list[i].title}</option>`;
                }
                articles_category_parent_select.html(code[0]);
                articles_category_select.html(code[1]);
                if (this.list.length) {
                    articles_category_parent_select.val(ids.includes(selected_category_parent) ? selected_category_parent : (articles_category_parent_select[0].selectedIndex > -1 ? this.list[articles_category_parent_select[0].selectedIndex].id : ''));
                    articles_category_select.val(ids.includes(selected_category) ? selected_category : (articles_category_select[0].selectedIndex > -1 ? this.list[articles_category_select[0].selectedIndex].id : ''));
                }
            },

            updateActive: function () {
                let id = this.activeID();
                if (id) {
                    let index = this.getIndex(id);
                    let language = articles_content_categories.find('.sb-language-switcher .sb-active').attr('data-language');
                    let category = { title: articles_content_categories.find('#category-title').val(), description: articles_content_categories.find('#category-description').val(), image: articles_content_categories.find('#category-image').attr('data-value') }
                    if (language) {
                        this.list[index].languages[language] = category;
                    } else {
                        category.id = SBF.stringToSlug(category.title);
                        category.parent = articles_content_categories.find('#category-parent').is(':checked');
                        category.languages = this.list[index].languages;
                        this.list[index] = category;
                        articles_area.find('.ul-categories .sb-active').html(category.title + '<i class="sb-icon-delete"></i>').attr('data-id', category.id);
                    }
                }
            },

            clear: function () {
                articles_content_categories.find('input, textarea').val('');
                articles_content_categories.find('#category-image').removeAttr('data-value style');
            },

            getIndex: function (category_id) {
                for (var i = 0; i < this.list.length; i++) {
                    if (this.list[i].id == category_id) {
                        return i;
                    }
                }
                return false;
            },

            activeID: function () {
                return articles_area.find('.ul-categories .sb-active').attr('data-id');
            },

            translations: {

                add: function (language_code, category_id = false) {
                    SBArticles.categories.updateActive();
                    if (!category_id) {
                        category_id = SBArticles.categories.activeID();
                    }
                    let index = SBArticles.categories.getIndex(category_id);
                    if (SBF.null(SBArticles.categories.list[index].languages)) SBArticles.categories.list[index].languages = {}; // Deprecated
                    SBArticles.categories.list[index].languages[language_code] = { title: '', description: '', image: '' };
                    articles_content_categories.sbLanguageSwitcher($.map(SBArticles.categories.list[index].languages, function (e, index) { return index }), 'article-categories', language_code);
                    SBArticles.categories.clear();
                },

                delete: function (language_code, category_id = false) {
                    let active_id = SBArticles.categories.activeID();
                    if (!category_id) {
                        category_id = SBArticles.categories.activeID(active_id);
                    }
                    delete SBArticles.categories.list[SBArticles.categories.getIndex(category_id)].languages[language_code];
                    SBArticles.categories.show(active_id);
                }
            }
        },

        translations: {
            list: {},

            add: function (language_code, article_id = false) {
                if (!article_id) {
                    article_id = SBArticles.activeID(true);
                }
                let translations = this.get(article_id);
                translations.push([language_code, false]);
                this.list[article_id] = translations;
                articles_content.sbLanguageSwitcher(translations, 'articles', language_code);
                SBArticles.clear();
            },

            delete: function (language_code, article_id = false) {
                if (!article_id) {
                    article_id = SBArticles.activeID(true);
                }
                let translations = this.get(article_id);
                for (var i = 0; i < translations.length; i++) {
                    if (translations[i][0] == language_code) {
                        SBArticles.delete(translations[i][1], (response) => {
                            if (response === true) {
                                translations.splice(i, 1);
                                this.list[article_id] = translations;
                                SBArticles.show(article_id);
                            }
                        });
                        break;
                    }
                }
                return false;
            },

            get: function (article_id) {
                return article_id in this.list ? this.list[article_id] : [];
            }
        }
    }

    /*
    * ----------------------------------------------------------
    * Reports
    * ----------------------------------------------------------
    */

    var SBReports = {
        charts: [],
        active_report_category_name: false,
        active_reports: false,
        active_date_range: false,
        pending_open: false,

        initChart: function (report_name, data, type = 'line', label_type = 1) {
            let values = [];
            let labels = [];
            let blues = SB_ADMIN_SETTINGS.color ? [SB_ADMIN_SETTINGS.color] : ['#049CFF', '#74C4F7', '#B9E5FF', '#0562A0', '#003B62', '#1F74C4', '#436786'];
            let canvas = admin.find(`[data-report-name="${report_name}"] canvas`);
            if (!canvas.length) {
                return;
            }
            for (var key in data) {
                values.push(data[key][0]);
                labels.push(key);
            }
            if (type != 'line' && values.length > 6) {
                for (var i = 0; i < values.length; i++) {
                    blues.push('hsl(' + 210 + ', ' + Math.floor(Math.random() * 100) + '%, ' + Math.floor(Math.random() * 100) + '%)');
                }
            }
            this.charts.push(new Chart(canvas, {
                type: type,
                data: {
                    labels: labels,
                    datasets: values && Array.isArray(values[0]) ? [
                        {
                            data: values.map(row => row[0]),
                            backgroundColor: '#1a9260',
                            borderRadius: 10,
                            barThickness: 20,
                            borderSkipped: false
                        },
                        {
                            data: values.map(row => row[1]),
                            backgroundColor: '#ca3434',
                            borderRadius: 10,
                            barThickness: 20,
                            borderSkipped: false
                        }
                    ] : [{
                        data: values,
                        backgroundColor: type == 'line' ? (SB_ADMIN_SETTINGS.color ? '#cbcbcb82' : '#028be530') : blues,
                        borderColor: type == 'line' ? (SB_ADMIN_SETTINGS.color ? SB_ADMIN_SETTINGS.color : '#049CFF') : '#FFFFFF',
                        borderWidth: 0,
                        borderRadius: 10,
                        barThickness: 20,
                        borderSkipped: false
                    }]
                },
                options: {
                    legend: {
                        display: false
                    },
                    scales: {
                        yAxes: [{
                            gridLines: {
                                display: type != 'pie' && type != 'horizontalBar',
                                drawBorder: false,
                                color: SBF.storage('dark-mode') ? '#444444' : '#ebebeb',
                                zeroLineColor: SBF.storage('dark-mode') ? '#444444' : '#ebebeb'
                            },
                            ticks: {
                                callback: function (tick_value) {
                                    return type != 'pie' ? (label_type == 1 ? tick_value : (label_type == 2 ? new Date(tick_value * 1000).toISOString().substr(11, 8) : tick_value)) : '';
                                },
                                beginAtZero: true
                            }
                        }],
                        xAxes: [{
                            gridLines: {
                                display: type == 'horizontalBar',
                                color: SBF.storage('dark-mode') ? '#444444' : '#ebebeb',
                                zeroLineColor: SBF.storage('dark-mode') ? '#444444' : '#ebebeb'
                            },
                            ticks: {
                                display: type != 'pie',
                                beginAtZero: true
                            }
                        }],
                    },
                    tooltips: {
                        mode: 'nearest',
                        intersect: false,
                        callbacks: {
                            label: function (tooltipItem, chartData) {
                                let index = tooltipItem.index;
                                let value = chartData.datasets[tooltipItem.datasetIndex].data[index];
                                switch (label_type) {
                                    case 1: return value;
                                    case 2: return new Date(values[index] * 1000).toISOString().substr(11, 8);
                                    case 3: return value + '%';
                                    case 4: return chartData.labels[index];
                                }
                            },
                        },
                        displayColors: false
                    },
                    hover: {
                        mode: 'nearest',
                        intersect: false
                    }
                }
            }));
        },

        initReport: function (category_name = false, date_range = false) {
            let area = reports_area.find('> .sb-scroll-area');
            date_range = SBF.null(date_range) ? [false, false] : date_range.split(' - ');
            area.sbLoading(true);
            if (category_name) {
                this.active_report_category_name = category_name;
            }
            if (!this.active_report_category_name) {
                return;
            }
            this.active_date_range = date_range;
            SBF.ajax({
                function: 'reports-get-code',
                name: this.active_report_category_name,
                date_start: date_range[0],
                date_end: date_range[1],
                timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
            }, (response) => {
                area.html(response.code).sbLoading(false);
                area.sbInitTooltips();
                this.charts.forEach((chart) => {
                    chart.destroy();
                });
                this.charts = [];
                this.active_reports = response.reports;
                for (let key in response.reports) {
                    this.initChart(key, response.reports[key].data, response.reports[key].chart_type, response.reports[key].label_type);
                }
                SBF.event('SBReportsLoaded', { report_category_name: this.active_report_category_name, date_range: date_range });
            });
        },

        export: function (report_name, onSuccess) {
            SBF.ajax({
                function: 'reports-export',
                name: report_name,
                date_start: this.active_date_range[0],
                date_end: this.active_date_range[1],
                timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
            }, (response) => {
                onSuccess(response);
            });
        },

        open: function (category_name) {
            header.find('.sb-admin-nav #sb-reports').click();
            this.pending_open = category_name;
        },

        openSingle: function (report_name) {
            const report = this.active_reports[report_name];
            let code = '<div class="sb-chart" data-report-name="' + report_name + '-panel"><canvas></canvas></div><table class="sb-table"><thead><tr>';
            let index = report.data[Object.keys(report.data)[0]].length - 1;
            let list = [];
            for (var h of report.table) {
                code += `<th>${h}</th>`;
            }
            code += '</tr></thead><tbody>';
            for (var key in report.data) {

                list.push([key, report.data[key][index]]);

            }
            if (report.table_inverse) {
                list.reverse();
            }
            for (var i = 0; i < list.length; i++) {
                code += `<tr><td><div>${list[i][0]}</div></td><td>${list[i][1]}</td></tr>`;
            }
            code += `</tbody></table>`;
            if (report.average) {
                code += `<div class="sb-report-total"><span>${report.average_label}</span><span>${report.average}</span></div>`;
            }
            SBAdmin.genericPanel('report', report.title, code, [['Export', 'file']], 'data-report-name="' + report_name + '"', true);
            this.initChart(report_name + '-panel', report.data, report.chart_type, report.label_type);
        }
    }

    /*
    * ----------------------------------------------------------
    * Users
    * ----------------------------------------------------------
    */

    var SBUsers = {
        real_time: null,
        datetime_last_user: '2000-01-01 00:00:00',
        sorting: ['creation_time', 'DESC'],
        user_types: ['visitor', 'lead', 'user'],
        user_main_fields: ['id', 'first_name', 'last_name', 'email', 'password', 'profile_image', 'user_type', 'creation_time', 'token', 'last_activity', 'department'],
        search_query: '',
        init: false,
        busy: false,
        table_extra: false,
        history: [],

        get: function (onSusccess, is_online_users = false, is_users_pagination = false) {
            let filters = [];
            for (var i = 0; i < users_filters.length; i++) {
                filters.push(users_filters.eq(i).find('li.sb-active').data('value'));
            }
            if (!is_users_pagination) {
                loading(users_table);
            }
            SBF.ajax({
                function: is_online_users ? 'get-online-users' : 'get-users',
                sorting: is_online_users ? this.sorting[0] : this.sorting,
                pagination: is_users_pagination ? users_pagination : false,
                user_types: this.user_types,
                search: this.search_query,
                extra: this.table_extra,
                department: filters[0],
                source: filters[1],
                tag: filters[2],
            }, (response) => {
                onSusccess(response);
                users_table.sbLoading(false);
            });
        },

        filter: function (user_type) {
            if (user_type == 'all') {
                user_type = ['visitor', 'lead', 'user'];
            } else if (user_type == 'agent') {
                user_type = ['agent', 'admin'];
            } else {
                user_type = [user_type];
            }
            this.user_types = user_type;
            users_pagination = 1;
            users_pagination_count = 1;
            this.get((response) => {
                this.populate(response);
            }, user_type[0] == 'online');
        },

        sort: function (field, direction = 'DESC') {
            this.sorting = [field, direction];
            users_pagination = 1;
            users_pagination_count = 1;
            this.get((response) => {
                this.populate(response);
            });
        },

        search: function (input) {
            searchInput(input, (search, icon) => {
                users_pagination = 1;
                users_pagination_count = 1;
                this.search_query = search;
                this.get((response) => {
                    this.user_types = ['visitor', 'lead', 'user'];
                    this.populate(response);
                    $(icon).sbLoading(false);
                    users_table_menu.find('li').sbActive(false).eq(0).sbActive(true);
                });
            });
        },

        populate: function (response) {
            let code = '';
            let count = response.length;
            if (count) {
                for (var i = 0; i < count; i++) {
                    code += this.getRow(new SBUser(response[i], response[i].extra));
                }
            } else {
                code = `<p class="sb-no-results">${sb_('No users found.')}</p>`;
            }
            users_table.parent().scrollTop(0);
            users_table.find('tbody').html(code);
            if (this.user_types.includes('agent')) {
                SBF.ajax({
                    function: 'get-online-users',
                    agents: true
                }, (response) => {
                    let ids = [];
                    for (var i = 0; i < response.length; i++) {
                        ids.push(response[i].id);
                    }
                    users_table.find('[data-user-id]').each(function () {
                        $(this).find('.sb-td-profile').addClass('sb-' + (ids.includes($(this).attr('data-user-id')) ? 'online' : 'offline'));
                    });
                });
            }
        },

        update: function () {
            if (!this.busy) {
                let checks = ['user', 'visitor', 'lead', 'agent'];
                let populate = checks.includes(this.user_types[0]) && !this.search_query;
                let filter = users_table_menu.find('.sb-active').data('type');
                if (filter == 'online') {
                    this.filter(filter);
                } else {
                    this.busy = true;
                    SBF.ajax({
                        function: 'get-new-users',
                        datetime: this.datetime_last_user
                    }, (response) => {
                        let count = response.length;
                        this.busy = false;
                        if (count > 0) {
                            let code = '';
                            for (var i = 0; i < count; i++) {
                                let user = new SBUser(response[i]);
                                users[user.id] = user;
                                this.updateMenu('add', user.type);
                                if (populate) {
                                    code += this.getRow(user);
                                }
                            }
                            if (populate) {
                                users_table.find('tbody').prepend(code);
                                if (checks.includes(filter)) {
                                    let selector = '';
                                    for (var i = 0; i < checks.length; i++) {
                                        selector += checks[i] == filter ? '' : `[data-user-type="${checks[i]}"],`;
                                    }
                                    users_table.find(selector.slice(0, -1)).remove();
                                }
                            }
                            this.datetime_last_user = response[0].creation_time;
                        }
                    });
                }
            }
        },

        getRow: function (user) {
            if (user instanceof SBUser) {
                let code = '';
                if (user.name.includes('open-ai-temp-user')) {
                    if (!chatbot_area.sbActive()) {
                        SBApps.openAI.playground.deleteData();
                    }
                    return '';
                }
                for (var i = 0; i < this.table_extra.length; i++) {
                    let slug = this.table_extra[i];
                    code += `<td class="sb-td-${slug}">${this.user_main_fields.includes(slug) ? user.get(slug) : user.getExtra(slug)}</td>`;
                }
                return `<tr data-user-id="${user.id}" data-user-type="${user.type}"><td><input type="checkbox" /></td><td class="sb-td-profile"><a class="sb-profile"><img loading="lazy" src="${user.image}" /><span>${user.name}</span></a></td>${code}<td class="sb-td-email">${user.get('email')}</td><td class="sb-td-ut">${sb_(user.type)}</td><td>${SBF.beautifyTime(user.get('last_activity'), true)}</td><td>${SBF.beautifyTime(user.get('creation_time'))}</td></tr>`;
            } else {
                SBF.error('User not of type SBUser', 'SBUsers.getRow');
                return false;
            }
        },

        updateRow: function (user) {
            let row = users_table.find(`[data-user-id="${user.id}"]`);
            if (row.length) {
                let menu_active = users_table_menu.find('.sb-active').data('type');
                if ((user.type != menu_active) && !(user.type == 'admin' && menu_active == 'agent') && menu_active != 'all') {
                    let counter = admin.find(`[data-type="${user.type == 'admin' ? 'agent' : user.type}"] span`);
                    let count = parseInt(counter.attr('data-count'));
                    counter.html(count + 1).attr('data-count', count + 1);
                    row.remove();
                } else {
                    row.replaceWith(this.getRow(user));
                }
            } else {
                users_table.find('tbody').append(this.getRow(user));
            }
        },

        updateMenu: function (action = 'all', type = false) {
            let user_types = ['all', 'user', 'lead', 'visitor'];
            if (action == 'all') {
                SBF.ajax({
                    function: 'count-users'
                }, (response) => {
                    for (var i = 0; i < user_types.length; i++) {
                        this.updateMenuItem('set', user_types[i], response[user_types[i]]);
                    }
                });
            } else {
                this.updateMenuItem(action, type);
            }
        },

        updateMenuItem: function (action = 'set', type = false, count = 1) {
            let item = users_table_menu.find(`[data-type="${type}"] span`);
            let user_types = ['user', 'lead', 'visitor'];
            if (action != 'set') {
                count = parseInt(item.attr('data-count')) + (1 * (action == 'add' ? 1 : -1));
            }
            item.html(`(${count})`).attr('data-count', count);
            count = 0;
            for (var i = 0; i < user_types.length; i++) {
                count += parseInt(users_table_menu.find(`[data-type="${user_types[i]}"] span`).attr('data-count'));
            }
            users_table_menu.find(`[data-type="all"] span`).html(`(${count})`).attr('data-count', count);
        },

        delete: function (user_ids) {
            loading(users_table);
            if (Array.isArray(user_ids)) {
                if (SB_ADMIN_SETTINGS.cloud) {
                    user_ids = SBCloud.removeAdminID(user_ids);
                    if (!user_ids.length) {
                        return;
                    }
                }
                SBF.ajax({
                    function: 'delete-users',
                    user_ids: user_ids
                }, () => {
                    for (var i = 0; i < user_ids.length; i++) {
                        delete users[user_ids[i]];
                        users_table.find(`[data-user-id="${user_ids[i]}"]`).remove();
                        conversations_admin_list_ul.find(`[data-user-id="${user_ids[i]}"]`).remove();
                        SBF.event('SBUserDeleted', user_ids[i]);
                    }
                    if (users_table.find('[data-user-id]').length == 0) {
                        this.filter(users_table_menu.find('.sb-active').data('type'));
                    }
                    infoBottom('Users deleted');
                    this.updateMenu();
                    users_table.sbLoading(false);
                });
            } else {
                users[user_ids].delete(() => {
                    let conversation = conversations_admin_list_ul.find(`[data-user-id="${user_ids}"]`);
                    if (activeUser().id == user_ids) {
                        activeUser(false);
                    }
                    if (conversation.sbActive()) {
                        SBChat.conversation = false;
                        setTimeout(() => { SBConversations.clickFirst() }, 300);
                    }
                    delete users[user_ids];
                    users_table.find(`[data-user-id="${user_ids}"]`).remove();
                    conversation.remove();
                    admin.sbHideLightbox();
                    infoBottom('User deleted');
                    this.updateMenu();
                    users_table.sbLoading(false);
                });
            }
        },

        startRealTime: function () {
            if (SBPusher.active) {
                return;
            }
            this.stopRealTime();
            this.real_time = setInterval(() => {
                this.update();
            }, 1000);
        },

        stopRealTime: function () {
            clearInterval(this.real_time);
        },

        csv: function () {
            SBF.ajax({ function: 'csv-users', users_id: SBUsers.getSelected() }, (response) => {
                dialogDeleteFile(response, 'sb-export-users-close', 'Users exported');
                window.open(response);
            });
        },

        updateUsersActivity: function () {
            SBF.updateUsersActivity(agent_online ? SB_ACTIVE_AGENT.id : -1, activeUser() ? activeUser().id : -1, function (response) {
                SBUsers.setActiveUserStatus(response == 'online');
            });
        },

        setActiveAgentStatus: function (online = true) {
            let label = online ? 'online' : 'offline';
            agent_online = online;
            header.find('[data-value="status"]').html(sb_(SBF.slugToString(label))).attr('class', 'sb-' + label);
            if (SBPusher.active) {
                if (online) {
                    SBPusher.presence();
                    if (SB_ADMIN_SETTINGS.routing == 'queue' || SB_ADMIN_SETTINGS.routing == 'routing') {
                        SBF.ajax({ function: 'assign-conversations-active-agent', is_queue: SB_ADMIN_SETTINGS.routing == 'queue' }, () => {
                            SBConversations.update();
                        });
                    }
                } else {
                    SBPusher.presenceUnsubscribe();
                }
            }
            if (!SB_ADMIN_SETTINGS.reports_disabled) {
                SBF.ajax({ function: 'reports-update', name: label });
            }
        },

        setActiveUserStatus: function (online = true) {
            let labels = conversations_area.find('.sb-conversation .sb-top > .sb-labels');
            labels.find('.sb-status-online').remove();
            if (online) labels.prepend(`<span class="sb-status-online">${sb_('Online')}</span>`);
            SBChat.user_online = online;
        },

        onlineUserNotification: function (member) {
            let notification = SB_ADMIN_SETTINGS.online_users_notification;
            if (notification) {
                let message = member.info.first_name + ' ' + member.info.last_name;
                let icon = this.userProfileImage(member.info.profile_image);
                if (SB_ADMIN_SETTINGS.push_notifications && member.info.id && !this.history.includes(member.info.id)) {
                    SBF.ajax({
                        function: 'push-notification',
                        title: notification,
                        message: message,
                        icon: icon,
                        interests: SB_ACTIVE_AGENT.id,
                        user_id: member.info.id
                    });
                } else if (SBConversations.desktop_notifications) {
                    SBChat.desktopNotification(notification, message, icon, false, member.info.id);
                }
                this.history.push(member.info.id);
            }
        },

        userProfileImage: function (url) {
            return !url || url.indexOf('user.svg') ? SB_ADMIN_SETTINGS.notifications_icon : url;
        },

        getSelected: function () {
            let user_ids = [];
            users_table.find('tr').each(function () {
                if ($(this).find('td input[type="checkbox"]').is(':checked')) {
                    user_ids.push($(this).attr('data-user-id'));
                }
            });
            return user_ids;
        },

        getExtraDetailsList: function (only_custom = false) {
            return profile_edit_box.find('.sb-additional-details .sb-edit-box > ' + (only_custom ? '.sb-custom-detail' : '.sb-input')).map(function () { return [[$(this).attr('id'), $(this).find('span').html().trim()]] }).get();
        }
    }

    /*
    * ----------------------------------------------------------
    * Conversations 
    * ----------------------------------------------------------
    */

    var SBConversations = {
        real_time: null,
        datetime_last_conversation: false,
        user_typing: false,
        desktop_notifications: false,
        flash_notifications: false,
        notifications_list: {},
        busy: false,
        busy_2: false,
        is_search: false,
        menu_count_ajax: false,
        previous_editor_text: false,
        message_drafts: {},
        active_calls: {},

        // Open the conversations tab
        open: function (conversation_id = -1, user_id) {
            if (conversation_id != -1) {
                this.openConversation(conversation_id, user_id);
            }
            admin.sbHideLightbox();
            header.find('.sb-admin-nav a').sbActive(false).parent().find('#sb-conversations').sbActive(true);
            admin.find(' > main > div').sbActive(false);
            conversations_area.sbActive(true).find('.sb-board').removeClass('sb-no-conversation');
            select_departments.find(' > p').attr('data-id', '').attr('data-value', '').html(sb_('None'));
            this.notes.update([]);
            this.tags.update([]);
            this.startRealTime();
        },

        // Open a single conversation
        openConversation: function (conversation_id, user_id = false, scroll = true) {
            SBChat.label_date.sbActive(false);
            SBChat.label_date_show = false;
            if (this.busy_2 == conversation_id) {
                return;
            }
            if (user_id === false && conversation_id) {
                this.busy_2 = conversation_id;
                SBF.ajax({
                    function: 'get-user-from-conversation',
                    conversation_id: conversation_id
                }, (response) => {
                    this.busy_2 = false;
                    if (!SBF.null(response.id)) {
                        this.openConversation(conversation_id, response.id, scroll);
                    } else {
                        this.clickFirst();
                    }
                });
            } else {
                let new_user = SBF.null(users[user_id]) || !(users[user_id].details.email);
                let conversation = conversations_area.find(`[data-conversation-id="${conversation_id}"]`);
                let conversation_list = conversations_admin_list_ul.find('li');
                let active_conversation = this.getSelectedConversations();
                conversations_area_list.html('');
                conversations_area_list.sbLoading(true);
                if (active_conversation.length) {
                    this.message_drafts[active_conversation[0].id] = editor_textarea.val().trim();
                    SBF.storage('message-drafts', this.message_drafts);
                }
                editor_textarea.val('');
                SBChat.insertText(this.message_drafts[conversation_id] ? this.message_drafts[conversation_id] : '');

                // Init the user
                if (new_user) {
                    activeUser(new SBUser({ id: user_id }));
                    activeUser().update(() => {
                        users[user_id] = activeUser();
                        this.updateUserDetails();
                    });
                } else {
                    activeUser(users[user_id]);
                    this.updateCurrentURL();
                }
                if (SBPusher.active) {
                    SBPusher.event('client-typing', (response) => {
                        if (response.user_id == activeUser().id) {
                            SBConversations.typing(true);
                            clearTimeout(pusher_timeout);
                            pusher_timeout = setTimeout(() => { SBConversations.typing(false) }, 1000);
                        }
                    });
                    SBPusher.event('new-message', (response) => {
                        if (response && response.action && ['message_delete', 'message_update'].includes(response.action)) {
                            SBChat.id_last_message_conversation = response.message_id - 2;
                            setTimeout(() => {
                                SBChat.update();
                            }, 1000);
                        } else {
                            SBChat.update();
                        }
                        if (response) {
                            if (response.terminate_call || response.incoming_call || response.call_response) {
                                SBF.call.show(response.incoming_call || response.call_response ? true : false, response.call_response && response.call_response.status == 'RINGING');
                                if (response.terminate_call) {
                                    delete this.active_calls[response.conversation_id];
                                    SBF.call.end();
                                } else {
                                    this.active_calls[response.conversation_id] = response.call_response ? response.call_response : response.incoming_call;
                                    if (response.call_response && response.call_response.status == 'ACCEPTED') {
                                        SBF.call.startCall();
                                    }
                                }
                            } else if (response.connect_call) {
                                if (SBF.call.rtc) {
                                    SBF.call.rtc.setRemoteDescription({
                                        type: 'answer',
                                        sdp: response.connect_call.session.sdp
                                    });
                                    profile_box.find('[data-value="whatsapp-call"]').sbLoading(false);
                                    SBConversations.open(response.conversation_id);
                                }
                            }
                        }
                    });
                    SBPusher.event('agent-active-conversation-changed', (response) => {
                        if (response.previous_conversation_id == conversation_id) {
                            conversations_area.find('.sb-conversation-busy').remove();
                        }
                    }, 'agents');
                    SBPusher.event('init', (response) => {
                        SBConversations.updateCurrentURL(response.current_url);
                    });
                    SBPusher.event('message-status-update', (response) => {
                        if (SBChat.conversation) {
                            SBChat.conversation.updateMessagesStatus(response.message_ids);
                        }
                    });
                }
                if (SB_ADMIN_SETTINGS.smart_reply) {
                    suggestions_area.html('');
                }

                // Open the conversation
                conversation_list.sbActive(false);
                if (!SB_ADMIN_SETTINGS.departments_show) {
                    conversation_list.attr('data-color', '');
                }
                conversation.sbActive(true);
                if (conversation_id != -1) {
                    this.busy_2 = conversation_id;
                    activeUser().getFullConversation(conversation_id, (response) => {
                        let conversation_status_code = response.status_code;
                        let select = conversations_filters.eq(0);
                        let select_status_code = select.find('.sb-active').attr('data-value');
                        let title = response.get('title');
                        this.busy_2 = false;
                        SBChat.setConversation(response);
                        SBChat.populate();
                        this.setReadIcon(conversation_status_code);
                        conversations_area.find('.sb-conversation-busy').remove();
                        this.updateUserDetails();
                        conversations_area.find('.sb-top > a').html(SBF.getFileType(title) == 'image' ? `<img src="${title}" />${title.includes('t=') ? ` <span>${new URL(title).searchParams.get('t')}</span>` : ''}` : title);

                        // Automatic translation
                        SBAdmin.must_translate = SB_ADMIN_SETTINGS.translation && activeUser().language && SB_ADMIN_SETTINGS.active_agent_language != activeUser().language;
                        if (SBAdmin.must_translate) {
                            let strings = [];
                            let message_ids = [];
                            let message_user_types = [];
                            let messages_translated = [];
                            for (var i = 0; i < response.messages.length; i++) {
                                let message = response.messages[i];
                                if (message.message) {
                                    if ((message.payload('original-message') && (!message.payload('original-message-language') || message.payload('original-message-language') == SB_ADMIN_SETTINGS.active_agent_language)) || (message.payload('translation') && (!message.payload('translation-language') || message.payload('translation-language') == SB_ADMIN_SETTINGS.active_agent_language))) {
                                        messages_translated.push(message);
                                    } else {
                                        strings.push(message.message);
                                        message_ids.push(message.id);
                                        message_user_types.push(message.get('user_type'));
                                    }
                                }
                            }
                            if (strings.length) {
                                SBApps.dialogflow.translate(strings, SB_ADMIN_SETTINGS.active_agent_language, (response_translate) => {
                                    if (response_translate) {
                                        for (var i = 0; i < response_translate.length; i++) {
                                            let message = SBChat.conversation.getMessage(message_ids[i]);
                                            message.payload('translation', response_translate[i])
                                            message.payload('translation-language', SB_ADMIN_SETTINGS.active_agent_language);
                                            this.openConversation_2(message_ids[i], message_user_types[i]);
                                        }
                                    }
                                    if (SB_ADMIN_SETTINGS.smart_reply) {
                                        this.openConversation_1(SBChat.conversation, suggestions_area);
                                    }
                                }, message_ids, conversation_id);
                            } else if (SB_ADMIN_SETTINGS.smart_reply) {
                                this.openConversation_1(SBChat.conversation, suggestions_area);
                            }
                            for (var i = 0; i < messages_translated.length; i++) {
                                this.openConversation_2(messages_translated[i].id, messages_translated[i].get('user_type'));
                            }
                        }

                        // Departments
                        if (select_departments.length) {
                            let department = response.get('department') ? this.getDepartments(response.get('department')) : false;
                            let color = department ? department['department-color'] : '';
                            if (!SB_ADMIN_SETTINGS.departments_show) {
                                conversation_list.attr('data-color', '');
                            }
                            getListConversation(conversation_id).attr('data-color', color);
                            select_departments.find(' > p').attr('data-id', department ? department['department-id'] : '').attr('data-value', color).html(department ? department['department-name'] + '<span></span>' : sb_('None'));
                        }

                        // Agent assignment
                        let select_agents = conversations_area.find('#conversation-agent');
                        if (select_agents.length) {
                            let item = select_agents.find(`[data-id="${response.get('agent_id')}"]`);
                            select_agents.find(' > p').attr('data-value', item.data('id')).html(item.html());
                        }

                        // Activate the conversation
                        if ([1, 2, '1', '2'].includes(conversation_status_code)) {
                            conversation_status_code = 0;
                        }
                        if (select_status_code != conversation_status_code && !$(conversations_admin_list).find('.sb-search-btn').sbActive() && !SBConversations.filters()[1] && !SBConversations.filters()[3]) {
                            select.find(`[data-value="${conversation_status_code}"]`).click();
                            select.find('ul').sbActive(false);
                        }
                        if (responsive) {
                            this.mobileOpenConversation();
                        }
                        if (!conversation.length && (select_status_code == conversation_status_code || (select_status_code == 0 && conversation_status_code == 1))) {
                            conversations_admin_list_ul.prepend(SBConversations.getListCode(response));
                        }
                        conversations_admin_list_ul.find('li').sbActive(false);
                        conversation.sbActive(true);
                        if (scroll) {
                            this.scrollTo();
                        }
                        this.notificationsCounterReset(conversation_id, conversation);
                        conversations_area_list.sbInitTooltips();

                        // Check if another agent has the conversation open
                        let busy = response.get('busy');
                        if (busy) {
                            conversations_area.find('.sb-editor > .sb-labels').prepend(`<span data-agent="${busy.id}" class="sb-status-warning sb-conversation-busy">${busy.first_name} ${busy.last_name} ${sb_('is replying to this conversation')}</span>`);
                        }

                        // App panels
                        if (SBApps.is('woocommerce')) {
                            SBApps.woocommerce.conversationPanel();
                        }
                        if (SBApps.is('ump')) {
                            SBApps.ump.conversationPanel();
                        }
                        if (SBApps.is('perfex')) {
                            SBApps.perfex.conversationPanel();
                        }
                        if (SBApps.is('whmcs')) {
                            SBApps.whmcs.conversationPanel();
                        }
                        if (SBApps.is('aecommerce')) {
                            SBApps.aecommerce.conversationPanel();
                        }
                        if (SBApps.is('martfury')) {
                            SBApps.martfury.conversationPanel();
                        }
                        if (SBApps.is('armember')) {
                            SBApps.armember.conversationPanel();
                        }
                        if (SBApps.is('zendesk')) {
                            SBApps.zendesk.conversationPanel();
                        }
                        if (SBApps.is('opencart')) {
                            SBApps.opencart.conversationPanel();
                        }
                        if (activeUser() && SB_ADMIN_SETTINGS.cloud) {
                            if (SBCloud.shopify.panel) {
                                SBCloud.shopify.panel.html('');
                            }
                            SBCloud.shopify.conversationPanel();
                        }
                        SBApps.calendar.conversationPanel();

                        // Notes and Tags
                        this.notes.update(response.details.notes);
                        this.tags.update(response.details.tags);

                        // Attachments
                        this.attachments();

                        // Suggestions
                        if (SB_ADMIN_SETTINGS.smart_reply && !SBAdmin.must_translate) {
                            this.openConversation_1(response, suggestions_area);
                        }

                        // Source tasks
                        let last_user_message = response.getLastUserMessage();
                        let active_call = ['connect_call', 'call_response', 'incoming_call'].includes(response.messages[response.messages.length - 1].payload('event')) ? response.messages[response.messages.length - 1].payload() : false;
                        if (response.get('source') == 'em') {
                            this.cc(response.get('extra').split(','));
                        }
                        if (last_user_message && response.get('source') == 'wa') {
                            if ((new Date()) - (new Date(last_user_message.get('creation_time').replace(' ', 'T'))) > 86400000) {
                                infoBottom(sb_('You can\'t send a WhatsApp message more than 24 hours after the user\'s last message—use a template instead.') + '<i id="sb-whatsapp-alert-btn" class="sb-icon-social-wa"</i>', 'info');
                            }
                        }
                        SBF.call.show(active_call ? true : false, active_call && active_call.response === 'RINGING');
                        if (active_call) {
                            this.active_calls[conversation_id] = { id: active_call.call_id, session: { sdp: active_call.sdp }, phone_number_id: active_call.phone_number_id };
                        }

                        // Populate user conversations on the bottom right area
                        activeUser().getConversations(function (response) {
                            conversations_area.find('.sb-user-conversations').html(response.length == 1 ? '' : activeUser().getConversationsCode(response)).prev().setClass('sb-hide', response.length == 1);
                        });

                        // Search
                        if (this.is_search) {
                            let search = conversations_admin_list.find('.sb-search-btn input').val();
                            for (var i = 0; i < response.messages.length; i++) {
                                if (response.messages[i].message.toLowerCase().includes(search)) {
                                    this.highlightMessage(response.messages[i].id);
                                }
                            }
                        }
                        conversations_area_list.sbLoading(false);
                    });
                } else {
                    SBChat.clear();
                    conversations_admin_list_ul.find('li').sbActive(false);
                    conversations_area_list.sbLoading(false);
                    conversations_area.find('.sb-top > a').html('');
                    if (!new_user) {
                        this.updateUserDetails();
                    }
                }

                // More settings
                conversations_area.find('.sb-board').removeClass('sb-no-conversation');
                SBConversations.previous_editor_text = false;
                SBUsers.updateUsersActivity();
                this.startRealTime();
                if (SBF.getURL('conversation') != conversation_id && conversation_id != -1) {
                    pushState('?conversation=' + conversation_id);
                }
            }
        },

        openConversation_1: function (response, suggestions_area) {
            let message = response.getLastUserMessage();
            suggestions_area.html('');
            if (message && message.payload('sb-human-takeover')) {
                message = response.getLastUserMessage(message.get('index'));
            }
            if (message) {
                SBApps.dialogflow.smartReply(message.message);
            }
        },

        openConversation_2: function (message_id, user_type) {
            let message = SBChat.conversation.getMessage(message_id);
            if (message) {
                let is_translation = SBF.isAgent(user_type) && user_type != 'bot';
                conversations_area_list.find(`[data-id="${message_id}"]`).replaceWith(message.getCode());
                conversations_area_list.find(`[data-id="${message_id}"] .sb-menu`).prepend(`<li data-value="${is_translation ? 'translation' : 'original'}">${sb_(is_translation ? 'View translation' : 'View original message')}</li>`);
            }
        },

        // Show a specific message and hightligh it
        highlightMessage: function (message_id) {
            setTimeout(() => {
                let label = '';
                conversations_area_list.find(`> div`).each(function () {
                    let message = $(this);
                    if (message.attr('data-id') == message_id) {
                        message.addClass('sb-highlight');
                        setTimeout(() => { message.removeClass('sb-highlight') }, 5000);
                        SBChat.label_date.html(label);
                        SBChat.label_date_show = true;
                        if (message.index()) {
                            message.prev()[0].scrollIntoView();
                        } else {
                            message[0].scrollIntoView();
                        }
                    } else if (message.hasClass('sb-label-date')) {
                        label = message.html();
                    }
                });
            }, 300);
        },

        getInfoMessage(message) {
            let event = message.payload('event');
            let agent_name = message.payload('agent_name');
            if (event) {
                if (agent_name) {
                    let value = event.split('-').pop();
                    if (SB_ACTIVE_AGENT.full_name == agent_name) {
                        agent_name = sb_('You');
                    }
                    if (event.includes('conversation-department-update')) {
                        return sb_('{R} assigned the conversation to the {R2} department.').replace('{R}', `<b>${agent_name}</b>`).replace('{R2}', `<b>${this.getDepartments(value) ? this.getDepartments(value)['department-name'] : value}</b>`);
                    } else if (event.includes('conversation-agent-update')) {
                        return sb_('{R} assigned the conversation to {R2}.').replace('{R}', `<b>${agent_name}</b>`).replace('{R2}', `<b>${message.payload('agent_name_assigned')}</b>`);
                    } else if (event.includes('conversation-status-update') && (value == 3 || value == 4)) {
                        return sb_('{R} {R2} the conversation.').replace('{R}', `<b>${agent_name}</b>`).replace('{R2}', `<b>${sb_(value == 3 ? 'archived' : 'deleted')}</b>`);
                    }
                } else if (event == 'incoming_call') {
                    return '<i class="sb-icon-phone-call-1"></i>' + sb_('Incoming voice call');
                } else if (event == 'terminate_call') {
                    const duration = message.payload('duration');
                    return `<span class="sb-info-message-btn" data-id="call"><i class="sb-icon-phone-call-${duration ? 1 : 2}"></i>${duration ? `${sb_('Voice call')} (${SBF.getMinutesSeconds(duration)}) </span>` : sb_('Call not answered')}`;
                } else if (event == 'call_permission_request') {
                    return `${sb_('Call permission request')} ${sb_(message.payload('response') == 'accept' ? 'accepted' : 'rejected')}`;
                } else if (event == 'call_response') {
                    return `<i class="sb-icon-phone-call-${['RINGING', 'ACCEPTED'].includes(message.payload('response')) ? 1 : 2}"></i>${sb_('Call')} ${sb_(message.payload('response').toLowerCase())}`;
                }
            }
            return '';
        },

        // Populate conversations
        populateList: function (response) {
            let code = '';
            conversations = [];
            for (var i = 0; i < response.length; i++) {
                code += this.getListCode(response[i]);
                conversations.push(new SBConversation([new SBMessage(response[i])], response[i]));
            }
            if (!code) {
                code = `<p class="sb-no-results">${sb_('No conversations found.')}</p>`;
            }
            conversations_admin_list_ul.html(code);
            this.updateMenu();
            SBF.event('SBAdminConversationsLoaded', { conversations: response });
        },

        // Update the left conversations list with latest conversations or messages 
        update: function () {
            if (this.busy) {
                return false;
            }
            if (conversations_filters.eq(0).find('p').attr('data-value') == 0 && this.datetime_last_conversation && active_admin_area == 'conversations') {
                let filters = SBConversations.filters();
                this.busy = true;
                SBF.ajax({
                    function: 'get-new-conversations',
                    datetime: this.datetime_last_conversation,
                    department: filters[1],
                    source: filters[2],
                    tag: filters[3],
                    agent_id: filters[4]
                }, (response) => {
                    this.busy = false;
                    if (response.length) {
                        let code_pending = '';
                        let code_not_pending = '';
                        let active_conversation_id = SBChat.conversation ? SBChat.conversation.id : -1;
                        let li_not_pending;
                        let scroll_to_conversation = false;
                        let id_check = [];
                        if (response[0].last_update_time) {
                            this.datetime_last_conversation = response[0].last_update_time;
                        }
                        for (var i = 0; i < response.length; i++) {
                            if (!id_check.includes(response[i].id)) {
                                let message = new SBMessage(response[i]);
                                let conversation = new SBConversation([message], response[i]);
                                let status_code = conversation.status_code;
                                let is_pending_status_code = status_code == 2 || (SB_ADMIN_SETTINGS.order_by_date && (status_code == 0 || status_code == 1));
                                let user_id = conversation.user_id;
                                let conversation_id = conversation.id;
                                let conversation_li = getListConversation(conversation_id);
                                let is_existing_conversation = conversation_li.length;
                                let user_type = message.get('user_type');
                                let message_text = conversation.get('message');
                                let active_conversation = active_conversation_id == conversation_id;
                                let is_user = !SBF.isAgent(user_type);
                                if (!message_text && message.payload('preview')) {
                                    message_text = message.payload('preview');
                                }
                                if (is_pending_status_code && (!active_conversation || SBF.visibility_status == 'hidden') && (is_user || message.payload('human-takeover-message-confirmation'))) {
                                    SBConversations.notifications_list = SBF.storage('notifications-counter');
                                    if (!SBConversations.notifications_list) {
                                        SBConversations.notifications_list = {};
                                    }
                                    if (!SBConversations.notifications_list[conversation_id]) {
                                        SBConversations.notifications_list[conversation_id] = [];
                                    }
                                    if (!SBConversations.notifications_list[conversation_id].includes(message.id)) {
                                        SBConversations.notifications_list[conversation_id].push(message.id);
                                        SBF.storage('notifications-counter', SBConversations.notifications_list);
                                    }
                                }
                                let conversation_code = this.getListCode(conversation, null);

                                // Active conversation
                                if (active_conversation) {
                                    this.updateUserDetails();
                                    if (is_existing_conversation) {
                                        if (message_text) {
                                            conversation_li.replaceWith(conversation_code);
                                        }
                                        this.setStatus(status_code, conversation_id);
                                    } else {
                                        scroll_to_conversation = true;
                                    }
                                } else if (is_existing_conversation) {

                                    // Conversation already in list but not active
                                    let conversation_ = conversations[conversation_li.index()];
                                    if (conversation_ && conversation instanceof SBConversation && conversation.messages.length == 1 && !conversation.messages[0].message && !conversation.messages[0].attachments.length) {
                                        conversation.messages[0].set('message', conversation_.messages[0].message);
                                        conversation.messages[0].set('attachments', conversation_.messages[0].attachments);
                                    }
                                    conversations[conversation_li.index()] = conversation;
                                    getListConversation(conversation_id).remove();
                                }

                                // Add the user to the global users array if it doesn't exists
                                if (!(user_id in users)) {
                                    users[user_id] = new SBUser({ id: user_id, first_name: conversation.get('first_name'), last_name: conversation.get('last_name'), profile_image: conversation.get('profile_image'), user_type: user_type });
                                }

                                // New or unactive conversation 
                                if (!active_conversation || !is_existing_conversation) {
                                    if (is_pending_status_code) {
                                        code_pending += conversation_code;
                                        conversations.unshift(conversation);
                                    } else if (status_code == 0 || status_code == 1) {
                                        li_not_pending = conversations_admin_list_ul.find('[data-conversation-status="2"]').last();
                                        if (li_not_pending.length) {
                                            conversations.splice(li_not_pending.index() + 1, 0, conversation);
                                            code_not_pending += conversation_code;
                                        } else {
                                            code_pending += conversation_code;
                                        }
                                    }
                                    if (activeUser() && user_id == activeUser().id) {
                                        activeUser().getConversations((response) => {
                                            conversations_area.find('.sb-user-conversations').html(activeUser().getConversationsCode(response));
                                        });
                                    }
                                    SBF.event('SBAdminNewConversation', { conversation: conversation });
                                }

                                // Update user
                                if (activeUser() && (message.payload('event') == 'update-user' || (users[user_id].type != user_type))) {
                                    activeUser().update(() => {
                                        this.updateUserDetails();
                                        users[activeUser().id] = activeUser();
                                    });
                                }

                                // Desktop, flash, sounds notifications
                                let message_preview = message.payload('preview');
                                if (!SBChat.tab_active && status_code == 2 && (is_user || message_preview) && (message_text || conversation.getAttachments().length || message_preview)) {
                                    if (this.desktop_notifications) {
                                        let user_details = [users[user_id].nameBeautified, users[user_id].image];
                                        SBChat.desktopNotification(user_details[0], message_preview ? message_preview : message_text, user_details[1], conversation_id, user_id);
                                    }
                                    if (this.flash_notifications) {
                                        SBChat.flashNotification();
                                    }
                                    if (SBChat.audio && SB_ADMIN_SETTINGS.sound) {
                                        SBChat.playSound();
                                    }
                                }
                                id_check.push(conversation_id);
                            }
                        }
                        if (!SBConversations.is_search) {
                            if (code_pending) {
                                conversations_admin_list_ul.prepend(code_pending);
                            }
                            if (code_not_pending) {
                                $(code_not_pending).insertAfter(li_not_pending);
                            }
                            if (scroll_to_conversation) {
                                this.scrollTo();
                            }
                            this.updateMenu();
                        }

                        // Update notifications counter
                        for (var i = 0; i < SBChat.notifications.length; i++) {
                            let is_found = false;
                            for (var j = 0; j < conversations.length; j++) {
                                if (conversations[j].id == SBChat.notifications[i][0]) {
                                    is_found = conversations[j].status_code == 2;
                                    break;
                                }
                            }
                            if (!is_found) {
                                SBChat.notifications.splice(i, 1);
                                i--;
                            }
                        }
                    }
                });
                if (SB_ADMIN_SETTINGS.assign_conversation_to_agent || SB_ACTIVE_AGENT.department) {
                    let ids = conversations_admin_list_ul.find(' > li').map(function () { return $(this).attr('data-conversation-id') }).get();
                    if (ids.length) {
                        SBF.ajax({
                            function: 'check-conversations-assignment',
                            conversation_ids: ids,
                            agent_id: SB_ADMIN_SETTINGS.assign_conversation_to_agent ? SB_ACTIVE_AGENT.id : false,
                            department: SB_ACTIVE_AGENT.department
                        }, (response) => {
                            if (response) {
                                for (var i = 0; i < response.length; i++) {
                                    getListConversation(response[i]).remove();
                                }
                            }
                        });
                    }
                }
            }
            return true;
        },

        // Update the top left filter
        updateMenu: function () {
            let count = conversations_admin_list_ul.find('[data-conversation-status="2"]').length;
            let item = conversations_filters.eq(0);
            let span = item.find(' > p span');
            if (count == 100 || this.menu_count_ajax || SB_ADMIN_SETTINGS.order_by_date) {
                let status_code = item.find('li.sb-active').data('value');
                this.menu_count_ajax = true;
                SBF.ajax({
                    function: 'count-conversations',
                    status_code: status_code == 0 ? 2 : status_code
                }, (response) => {
                    span.html(`(${response})`);
                });
            } else {
                span.html(`(${count})`);
            }
        },

        // Return the code of the message menu
        messageMenu: function (agent, message = false, reply = false) {
            let code = (message && SB_ADMIN_SETTINGS.chatbot_features ? `<li data-value="bot">${sb_('Train chatbot')}</li>` : '') + ((agent && !SB_ADMIN_SETTINGS.supervisor && SB_ADMIN_SETTINGS.allow_agent_delete_message) || (SB_ADMIN_SETTINGS.supervisor && SB_ADMIN_SETTINGS.allow_supervisor_delete_message) ? `<li data-value="delete">${sb_('Delete')}</li>` : '') + (reply ? `<li data-value="reply">${sb_('Reply')}</li>` : '');
            return `<i class="sb-menu-btn sb-icon-menu"></i><ul class="sb-menu">${code}</ul>`;
        },

        // Update the users details of the conversations area
        updateUserDetails() {
            if (!activeUser()) return;
            conversations_area.find(`[data-user-id="${activeUser().id}"] .sb-name`).html(activeUser().name);
            conversations_area.find(`.sb-top > a`).html(SBChat.conversation ? SBChat.conversation.title : activeUser().name);
            conversations_user_details.find('.sb-profile').setProfile();
            SBProfile.populate(activeUser(), conversations_area.find('.sb-panel-conversation-details'));
        },

        // Set the read status icon
        setReadIcon(status_code) {
            let unread = status_code == 2;
            conversations_area.find('.sb-top [data-value="read"],.sb-top [data-value="unread"]').sbActive([0, 1, 2].includes(parseInt(status_code))).attr('data-value', unread ? 'read' : 'unread').attr('data-sb-tooltip', sb_(unread ? 'Mark as read' : 'Mark as unread')).parent().sbInitTooltips().find('i').attr('class', unread ? 'sb-icon-check-circle' : 'sb-icon-circle');
        },

        // Set a conversation as read 
        setStatus(status_code, conversation_id = false, update_left_list = false) {
            if (!conversation_id) {
                conversation_id = SBChat.conversation.id;
            }
            if (conversation_id) {
                conversations[getListConversation(conversation_id).index()].set('status_code', status_code);
                this.setReadIcon(status_code);
                if (update_left_list) {
                    getListConversation(conversation_id).attr('data-conversation-status', status_code);
                }
            }
        },

        // Return the conversation code of the left conversations list
        getListCode: function (conversation, status) {
            if (!(conversation instanceof SBConversation)) {
                conversation = new SBConversation([new SBMessage(conversation)], conversation);
            }
            if (conversation.details.title == 'open-ai-temp-conversation') {
                if (!chatbot_area.sbActive()) {
                    SBApps.openAI.playground.deleteData();
                }
                return '';
            }
            let message = conversation.getCode(true);
            let label_new = '';
            let tags = SB_ADMIN_SETTINGS.tags_show ? conversation.get('tags') : '';
            let department_id = conversation.get('department');
            let notification_counter_code = '';
            let time = conversation.get('last_update_time');
            let is_active = SBChat.conversation && SBChat.conversation.id == conversation.id;
            if (SBF.null(status)) {
                status = conversation.status_code;
            }
            if (tags) {
                tags = SBConversations.tags.codeLeft(tags);
            }
            if (!SBChat.conversation || !is_active || SBF.visibility_status == 'hidden') {
                let notification_counter = SBF.storage('notifications-counter');
                if (notification_counter && notification_counter[conversation.id] && notification_counter[conversation.id].length) {
                    if (status == 2) {
                        notification_counter_code = `<span class="sb-notification-counter">${notification_counter[conversation.id].length}</span>`;
                    } else {
                        notification_counter[conversation.id] = [];
                        SBF.storage('notifications-counter', notification_counter);
                        this.notifications_list = notification_counter;
                    }
                }
            }
            if (!time) {
                time = conversation.getLastMessage() ? conversation.getLastMessage().get('creation_time') : conversation.get('creation_time');
            }
            return `<li${is_active ? ' class="sb-active"' : ''} data-user-id="${conversation.get('user_id')}" data-conversation-id="${conversation.id}" data-conversation-status="${status}"${department_id ? ` data-department="${department_id}"${SB_ADMIN_SETTINGS.departments_show ? ' data-color="' + this.getDepartments(department_id)['department-color'] + '"' : ''}` : ''}${!SBF.null(conversation.get('source')) ? ` data-conversation-source="${conversation.get('source')}"` : ''}>${label_new + notification_counter_code}<div class="sb-profile"><img loading="lazy" src="${conversation.get('profile_image')}"><span class="sb-name">${conversation.get('first_name') + ' ' + conversation.get('last_name')}</span>${tags}<span class="sb-time">${SBF.beautifyTime(time)}</span></div><p>${message}</p></li>`;
        },

        // Start or stop the real time update of left conversations list and chat 
        startRealTime: function () {
            if (SBPusher.active) {
                return;
            }
            this.stopRealTime();
            this.real_time = setInterval(() => {
                this.update();
                this.updateCurrentURL();
            }, 10000);
            SBChat.startRealTime();
        },
        stopRealTime: function () {
            clearInterval(this.real_time);
            SBChat.stopRealTime();
        },

        // Transcript generation and download
        transcript: function (conversation_id, user_id, action = false, onSuccess = false) {
            SBF.ajax({
                function: 'transcript',
                conversation_id: conversation_id
            }, (response) => {
                if (action == 'email') {
                    if (!activeUser() || activeUser().id != user_id || activeUser().get('email')) {
                        SBChat.sendEmail(SB_ADMIN_SETTINGS.transcript_message, [[response, response]], user_id, (response2) => {
                            if (onSuccess) {
                                onSuccess(response2 === true ? response : response2);
                            }
                        });
                    }
                } else {
                    if (onSuccess) {
                        onSuccess(response);
                    }
                    window.open(response);
                }
            });
        },

        // Set the typing status
        typing: function (typing) {
            if (typing) {
                if (!SBChat.user_online) {
                    SBUsers.setActiveUserStatus(true);
                }
                if (!this.user_typing) {
                    conversations_area.find('.sb-conversation .sb-top > .sb-labels').append('<span class="sb-status-typing">' + sb_('Typing') + '</span>');
                    this.user_typing = true;
                }
            } else if (this.user_typing) {
                conversations_area.find('.sb-conversation .sb-top .sb-status-typing').remove();
                this.user_typing = false;
            }
        },

        // Scroll the left conversations list to the active conversation
        scrollTo: function () {
            let active = conversations_admin_list_ul.find('.sb-active');
            let offset = active.length ? active[0].offsetTop : 0;
            conversations_admin_list_ul.parent().scrollTop(offset - (responsive ? 120 : 80));
        },

        // Search conversations
        search: function (input) {
            if (!input) return;
            searchInput(input, (search, icon) => {
                pagination_count = 1;
                if (search.length > 1) {
                    SBF.ajax({
                        function: 'search-conversations',
                        search: search
                    }, (response) => {
                        SBConversations.populateList(response);
                        $(icon).sbLoading(false);
                        this.scrollTo();
                        this.is_search = true;
                    });
                } else {
                    let filters = SBConversations.filters();
                    pagination = 1;
                    SBF.ajax({
                        function: 'get-conversations',
                        status_code: filters[0],
                        department: filters[1],
                        source: filters[2],
                        tag: filters[3],
                        agent_id: filters[4]
                    }, (response) => {
                        SBConversations.populateList(response);
                        $(icon).sbLoading(false);
                        this.is_search = false;
                        if (SBChat.conversation) {
                            getListConversation(SBChat.conversation.id).sbActive(true);
                            this.scrollTo();
                        }
                    });
                }
            });
        },

        // Reset the notifications counter of a conversation in the left list
        notificationsCounterReset: function (conversation_id, conversation = false) {
            let notification_counter = SBF.storage('notifications-counter');
            if (notification_counter && notification_counter[conversation_id]) {
                if (!conversation) {
                    conversation = conversations_admin_list_ul.find('[data-conversation-id="' + conversation_id + '"]');
                }
                let span = conversation.find('.sb-notification-counter');
                notification_counter[conversation_id] = [];
                SBF.storage('notifications-counter', notification_counter);
                this.notifications_list = notification_counter;
                span.addClass('sb-fade-out');
                setTimeout(() => {
                    span.remove();
                }, 200);
            }
        },

        getNotificationsCounterCount: function () {
            let notifications_counter = SBF.storage('notifications-counter');
            let notifications_counter_ = {};
            let count = 0;
            if (notifications_counter) {
                for (let key in notifications_counter) {
                    if (notifications_counter[key] && notifications_counter[key].length) {
                        count += notifications_counter[key].length;
                        notifications_counter_[key] = notifications_counter[key];
                    }
                }
                SBF.storage('notifications-counter', notifications_counter_);
            }
            return count;
        },

        // Get the page URL of the user
        updateCurrentURL: function (url = false) {
            if (url) {
                this.ucurl(url);
            } else if (SBChat.user_online && activeUser() && activeUser().getExtra('current_url')) {
                SBF.ajax({
                    function: 'current-url'
                }, (response) => {
                    if (response) this.ucurl(response);
                });
            }
        },

        ucurl(url) {
            let extra = activeUser().getExtra('current_url');
            url = urlStrip(url);
            conversations_area.find('.sb-profile-list [data-id="current_url"] label').attr('data-value', url).html(url);
            if (extra) {
                extra.value = url;
                activeUser().setExtra('current_url', extra);
            }
        },

        // Update the department of a conversation
        assignDepartment: function (conversation_id, department, onSuccess) {
            SBF.ajax({
                function: 'update-conversation-department',
                conversation_id: conversation_id,
                department: department,
                message: SBChat.conversation.getLastMessage().message
            }, (response) => {
                onSuccess(response);
            });
        },

        // Update the agent assignged to a conversation
        assignAgent: function (conversation_id, agent_id, onSuccess = false) {
            SBF.ajax({
                function: 'update-conversation-agent',
                conversation_id: conversation_id,
                agent_id: agent_id,
                message: SBChat.conversation.getLastMessage().message
            }, (response) => {
                if (onSuccess) onSuccess(response);
            });
        },

        // Update the UI to display the active department of the conversation
        setActiveDepartment: function (department_id) {
            if (SBChat.conversation && SBChat.conversation.get('department') == department_id) {
                return;
            }
            let department = department_id ? this.getDepartments(department_id) : false;
            let departmnet_color = department ? department['department-color'] : '';
            let conversation_li = getListConversation(SBChat.conversation.id);
            let department_filter = SBConversations.filters()[1];
            select_departments.find(' > p').attr('data-id', department ? department['department-id'] : '').attr('data-value', departmnet_color).html((department ? department['department-name'] : sb_('None')) + '<span></span>').next().sbActive(false);
            SBChat.conversation.set('department', department_id);
            if ((department_filter && department_filter != department_id) || (SB_ACTIVE_AGENT.user_type == 'agent' && SB_ACTIVE_AGENT.department && SB_ACTIVE_AGENT.department != department_id)) {
                conversation_li.remove();
                SBConversations.clickFirst();
            } else {
                conversation_li.attr('data-color', departmnet_color);
            }
            infoBottom('Department updated. The agents have been notified.');
        },

        // Get all departmnts or a single department
        getDepartments: function (department_id = false) {
            if (department_id) {
                for (var i = 0; i < SB_ADMIN_SETTINGS.departments.length; i++) {
                    if (SB_ADMIN_SETTINGS.departments[i]['department-id'] == department_id) {
                        return SB_ADMIN_SETTINGS.departments[i];
                    }
                }
                return false;
            }
            return SB_ADMIN_SETTINGS.departments;
        },

        // Update the UI to display the active agent of the conversation
        setActiveAgent: function (agent_id) {
            let select = conversations_area.find('#conversation-agent');
            let li = select.find(`[data-id="${agent_id}"]`);
            SBChat.conversation.set('agent_id', agent_id);
            select.find(' > p').attr('data-value', li.data('id')).html(li.html()).next().sbActive(false);
            if (SB_ACTIVE_AGENT.user_type == 'agent' && (!SB_ADMIN_SETTINGS.assign_conversation_to_agent || agent_id)) {
                getListConversation(SBChat.conversation.id).remove();
                SBConversations.clickFirst();
            }
            if (agent_id) {
                infoBottom('Agent assigned. The agent has been notified.');
            }
        },

        // Get the selected conversations from the left list
        getSelectedConversations: function () {
            return conversations_admin_list_ul.find('.sb-active').map(function () {
                return { id: $(this).attr('data-conversation-id'), user_id: $(this).attr('data-user-id'), status_code: $(this).attr('data-conversation-status') };
            }).toArray();
        },

        // Mobile conversations menu
        mobileOpenConversation: function () {
            conversations_area.find('.sb-admin-list').sbActive(false);
            conversation_area.sbActive(true);
            header.addClass('sb-hide');
        },

        mobileCloseConversation: function () {
            conversations_admin_list_ul.find('li.sb-active').sbActive(false);
            conversations_area.find('.sb-admin-list').sbActive(true);
            conversations_area.find('.sb-conversation,.sb-user-details').removeClass('sb-active');
            admin.find('.sb-menu-mobile [data-value="panel"]').sbActive(false);
            header.removeClass('sb-hide');
            window.history.replaceState({}, document.title, SBF.URL());
        },

        // Trigger the click event of the first conversation
        clickFirst: function (conversation_li = false) {
            if (!conversation_li || !conversation_li.length) {
                conversation_li = conversations_admin_list_ul.find('li:first-child');
            }
            if (conversation_li.length) {
                conversation_li.click();
                SBConversations.scrollTo();
            } else {
                conversations_area.find('.sb-board').addClass('sb-no-conversation');
                if (!conversations_admin_list_ul.find('li').length) {
                    conversations_admin_list_ul.html(`<p class="sb-no-results">${sb_('No conversations found.')}</p>`);
                }
                if (SBF.getURL('conversation')) {
                    window.history.replaceState({}, document.title, SBF.URL().replace('?conversation=' + SBF.getURL('conversation'), ''));
                }
            }
        },

        // Saved replies
        savedReplies: function (textarea, value) {
            let last_char = value.charAt(textarea.selectionStart - 1);
            let pre_text = value.substr(0, value.lastIndexOf('#'));
            if (last_char == '#') {
                if (value.length > 1 && value.charAt(textarea.selectionStart - 2) == '#') {
                    $(textarea).val(pre_text.substr(0, pre_text.length - 1));
                    return conversation_area.find('.sb-btn-saved-replies').click();
                }
                SBChat.editor_listening = true;
            }
            if (SBChat.editor_listening && last_char == ' ') {
                let keyword = value.substr(value.lastIndexOf('#') + 1).replace(' ', '');
                SBChat.editor_listening = false;
                for (var i = 0; i < saved_replies_list.length; i++) {
                    if (saved_replies_list[i]['reply-name'] == keyword) {
                        $(textarea).val(pre_text + saved_replies_list[i]['reply-text']);
                        return;
                    }
                }
            }
        },

        // Conversation attachments panel
        attachments: function () {
            if (attachments_panel.length) {
                let attachments = SBChat.conversation.getAttachments();
                let code = '';
                let code_filters = '';
                let file_types = [];

                for (var i = attachments.length - 1; i > -1; i--) {
                    let file_type = SBF.getFileType(attachments[i][1]);
                    code += `<a href="${attachments[i][1]}" target="_blank"><img src="${SB_URL}/media/files/${SBF.getFileIcon(attachments[i][1])}.svg">${attachments[i][0]}</a>`;
                    if (!file_types.includes(file_type)) {
                        file_types.push(file_type);
                    }
                }
                if (attachments.length > 4 && file_types.length > 1) {
                    code_filters = `<div id="sb-attachments-filter" class="sb-select"><p>${sb_('All')}</p><ul><li data-value="">${sb_('All')}</li>`;
                    for (var i = 0; i < file_types.length; i++) {
                        code_filters += `<li data-value="${file_types[i]}">${sb_(SBF.slugToString(file_types[i]) + 's')}</li>`;
                    }
                    code_filters += `</ul></div>`;
                }
                $(attachments_panel).html(code ? `<h3${code_filters ? ' class="sb-flex"' : ''}>${sb_('Attachments')}${code_filters}</h3><div class="sb-list-items sb-list-links">${code}</div>` : '');
                collapse(attachments_panel, 160);
            }
        },

        // Get conversations filters values
        filters: function () {
            let values = [];
            for (var i = 0; i < conversations_filters.length; i++) {
                values.push(conversations_filters.eq(i).find('li.sb-active').data('value'));
            }
            return values;
        },

        // Notes
        notes: {
            busy: false,

            add: function (conversation_id, user_id, name, message, onSuccess = false, note_id = false) {
                SBF.ajax({
                    function: note_id ? 'update-note' : 'add-note',
                    conversation_id: conversation_id,
                    user_id: user_id,
                    note_id: note_id,
                    name: name,
                    message: message
                }, (response) => {
                    if (onSuccess) {
                        onSuccess(response);
                    }
                });
            },

            update: function (notes, add = false) {
                if (notes_panel.length) {
                    let code = '';
                    let div = notes_panel.find(' > div');
                    if (notes) {
                        for (var i = 0; i < notes.length; i++) {
                            let note = notes[i];
                            code += `<div data-id="${note.id}"><span${SB_ADMIN_SETTINGS.notes_hide_information ? ' class="sb-note-hide-info"' : ''}>${SB_ADMIN_SETTINGS.notes_hide_information ? '' : note.name}${SB_ADMIN_SETTINGS.notes_hide_information || !note.date ? '' : `<span>${SBF.beautifyTime(note.date, true)}</span>`}${SB_ACTIVE_AGENT.id == note.user_id ? '<i class="sb-edit-note sb-icon-edit"></i><i class="sb-delete-note sb-icon-close"></i>' : ''}</span><span class="sb-note-text">${note.message.replace(/\n/g, '<br>')}</span></div>`;
                        }
                        code = code.autoLink({ target: '_blank' });
                    }
                    if (add) {
                        div.append(code);
                    } else {
                        div.html(code);
                    }
                    div.attr('style', '');
                    notes_panel.find('.sb-collapse-btn').remove();
                    collapse(notes_panel, 155);
                    this.busy = false;
                }
            },

            delete: function (conversation_id, note_id, onSuccess = false) {
                if (this.busy) return;
                this.busy = true;
                SBF.ajax({
                    function: 'delete-note',
                    conversation_id: conversation_id,
                    note_id: note_id
                }, (response) => {
                    this.busy = false;
                    if (onSuccess) onSuccess(response);
                });
            }
        },

        // Tags
        tags: {
            busy: false,

            update: function (tags) {
                if (tags_panel.length) {
                    let code = '';
                    let div = tags_panel.find(' > div');
                    for (var i = 0; i < tags.length; i++) {
                        let tag = this.get(tags[i]);
                        if (tag) {
                            code += this.code(tag);
                        }
                    }
                    div.html(code);
                    this.busy = false;
                }
            },

            get: function (tag_name) {
                for (var i = 0; i < SB_ADMIN_SETTINGS.tags.length; i++) {
                    if (tag_name == SB_ADMIN_SETTINGS.tags[i]['tag-name']) {
                        return SB_ADMIN_SETTINGS.tags[i];
                    }
                }
            },

            getAll: function (active_tags = []) {
                let code = '';
                for (var i = 0; i < SB_ADMIN_SETTINGS.tags.length; i++) {
                    code += this.code(i, active_tags.includes(SB_ADMIN_SETTINGS.tags[i]['tag-name']));
                }
                return code;
            },

            code: function (index_or_tag, active) {
                let tag = isNaN(index_or_tag) ? index_or_tag : SB_ADMIN_SETTINGS.tags[index_or_tag];
                if (tag) {
                    let name = tag['tag-name'];
                    return `<span data-value="${name}" data-color="${tag['tag-color']}"${active ? ' class="sb-active"' : ''}>${sb_(name)}</span>`;
                }
                return '';
            },

            codeLeft: function (tags) {
                let code = '<span class="sb-tags-area">';
                for (var i = 0; i < tags.length; i++) {
                    let tag = this.get(tags[i]);
                    if (tag) {
                        code += `<i class="sb-icon-tag" data-color-text="${tag['tag-color']}"></i>`;
                    }
                }
                return code + '</span>';
            }
        },

        // Direct message
        showDirectMessageBox: function (type, user_ids = []) {
            if (type == 'whatsapp') {
                whatsapp_direct_message_box(user_ids);
            } else {
                let email = type == 'custom_email';
                let names = { sms: 'text message', custom_email: 'email', message: 'chat message' };
                SBForm.clear(direct_message_box);
                direct_message_box.find('.sb-direct-message-users').val(user_ids.length ? user_ids.join(',') : 'all');
                direct_message_box.find('.sb-bottom > div').html('');
                direct_message_box.find('.sb-top-bar > div:first-child').html(sb_(`Send a ${names[type]}`));
                direct_message_box.find('.sb-loading').sbLoading(false);
                direct_message_box.find('.sb-direct-message-subject').sbActive(email).find('input').attr('required', email);
                direct_message_box.attr('data-type', type);
                direct_message_box.sbShowLightbox();
            }
        },

        // Miscellaneous 
        getDeliveryFailedMessage: function (source) {
            return `<i class="sb-icon-warning sb-delivery-failed" data-sb-tooltip="${sb_('Message not delivered to {R}.').replace('{R}', SBApps.getMessagingAppName(source))}" data-sb-tooltip-init></i>`;
        },

        cc: function (cc) {
            let code = '';
            for (var i = 0; i < cc.length; i++) {
                if (cc[i]) {
                    code += `<li data-id="cc"><i class="sb-icon sb-icon-envelope"></i><span>CC</span><label>${cc[i]}</label></li>`;
                }
            }
            conversations_area.find('[data-id="cc"]').remove();
            conversations_area.find('[data-id="email"]').attr('data-em', 'true').after(code);
        }
    }

    /* 
    * ----------------------------------------------------------
    * Profile
    * ----------------------------------------------------------
    */

    var SBProfile = {

        // Get all profile settings
        getAll: function (profile_area) {
            return SBForm.getAll(profile_area);
        },

        // Get a single setting
        get: function (input) {
            return SBForm.get(input);
        },

        // Set a single setting
        set: function (item, value) {
            return SBForm.set(item, value);
        },

        // Display the user box
        show: function (user_id) {
            loadingGlobal();
            activeUser(new SBUser({ id: user_id }));
            activeUser().update((response) => {
                if (!response) {
                    admin.sbHideLightbox();
                    return;
                }
                this.populate(activeUser(), profile_box.find('.sb-profile-list'));
                profile_box.find('.sb-profile').setProfile();
                activeUser().getConversations((response) => {
                    let user_type = activeUser().type;
                    let html = activeUser().getConversationsCode(response);
                    if (SBF.isAgent(user_type)) {
                        this.agentData();
                    }
                    profile_box.find('.sb-user-conversations').html(html).prev().setClass('sb-hide', !html);
                    profile_box.find('.sb-top-bar [data-value]').sbActive(false);
                    if (!SBF.null(activeUser().get('email'))) {
                        profile_box.find('.sb-top-bar [data-value="custom_email"]').sbActive(true);
                    }
                    if (activeUser().getExtra('phone')) {
                        if (SB_ADMIN_SETTINGS.sms) {
                            profile_box.find('.sb-top-bar [data-value="sms"]').sbActive(true);
                        }
                        profile_box.find('.sb-top-bar [data-value="whatsapp"],.sb-top-bar [data-value="whatsapp-call"]').sbActive(true);
                    }
                    this.boxClasses(profile_box, user_type);
                    profile_box.attr('data-user-id', activeUser().id).sbShowLightbox();
                    profile_box.find('.sb-start-conversation').setClass('sb-hide', response.length == 1 && response[0].get('extra_3') == 'call');
                    loadingGlobal(false, false);
                    SBF.event('SBProfileBoxOpened', { user_id: user_id });
                });
                users[user_id] = activeUser();
                if (SBF.getURL('user') != user_id && !SBF.getURL('conversation')) {
                    pushState('?user=' + user_id);
                }
            });
        },

        showEdit: function (user) {
            if (user instanceof SBUser) {
                let password = profile_edit_box.find('#password input');
                let current_user_type = user.type;
                let select = profile_edit_box.find('#user_type select');
                profile_edit_box.removeClass('sb-user-new').attr('data-user-id', user.id);
                profile_edit_box.find('.sb-top-bar .sb-save').html(`<i class="sb-icon-check"></i>${sb_('Save changes')}`);
                profile_edit_box.find('.sb-profile').setProfile();
                profile_edit_box.find('.sb-unlisted-detail').remove();
                profile_edit_box.find('input,select,textara').removeClass('sb-error');

                // Custom details
                let code = '';
                let default_ids = profile_edit_box.find('.sb-additional-details [id]').map(function () { return this.id; }).get().concat(['wp-id', 'perfex-id', 'whmcs-id', 'aecommerce-id', 'facebook-id', 'ip', 'os', 'current_url', 'country_code', 'browser_language', 'browser', 'martfury-id', 'martfury-session']);
                for (var id in user.extra) {
                    if (!default_ids.includes(id)) {
                        code += `<div id="${id}" data-type="text" class="sb-input sb-unlisted-detail"><span>${sb_(user.extra[id].name)}</span><input type="text"></div>`;
                    }
                }
                profile_edit_box.find('.sb-additional-details .sb-edit-box').append(code);

                // Set values
                this.populateEdit(user, profile_edit_box);
                this.updateRequiredFields(current_user_type);

                // User type select
                if (SB_ACTIVE_AGENT.user_type == 'admin' && SBF.isAgent(current_user_type)) {
                    select.html(`<option value="agent">${sb_('Agent')}</option><option value="admin"${current_user_type == 'admin' ? ' selected' : ''}>${sb_('Admin')}</option>`);
                }

                // Password
                if (password.val()) {
                    password.val('********');
                }

                // Cloud
                if (SB_ADMIN_SETTINGS.cloud) {
                    profile_edit_box.setClass('sb-cloud-admin', user.id == 1);
                }

                // Show the edit box
                this.boxClasses(profile_edit_box, current_user_type);
                profile_edit_box.sbShowLightbox();
                SBF.event('SBProfileEditBoxOpened', { user_id: user.id });
            } else {
                SBF.error('User not of type SBUser', 'SBUsers.showEdit');
                return false;
            }
        },

        // Populate profile
        populate: function (user, profile_area, is_extra = true) {
            let exclude = ['first_name', 'last_name', 'password', 'profile_image'];
            let code = ['', '', ''];
            if (profile_area.hasClass('sb-panel-conversation-details') && SBChat.conversation) {
                let source = SBChat.conversation.get('source');
                code[1] = this.profileRow('conversation-id', SBChat.conversation.id, sb_('Conversation ID'));
                if (!SBF.null(source)) {
                    let label = SBApps.getMessagingAppName(source);
                    let extra = SBChat.conversation.get(source == 'tg' ? 'extra_3' : 'extra');
                    let extra_2 = false;
                    let extra_3 = SBChat.conversation.get('extra_3');
                    if (extra_3) {
                        if (source == 'ig') {
                            label = 'Instagram' + ' ' + sb_('comment');
                            extra_2 = JSON.parse(extra_3)[0];
                        } else if (source == 'fb') {
                            label = 'Facebook' + ' ' + sb_('comment');
                            extra_2 = extra_3;
                        }
                    } else if (SB_ADMIN_SETTINGS.channel_labels[extra]) {
                        label = SB_ADMIN_SETTINGS.channel_labels[extra];
                    }
                    code[1] += this.profileRow('conversation-source', label, sb_('Source'), SBApps.getMessagingAppName(source), extra_2);
                }
                let messages = SBChat.conversation.messages;
                for (var i = messages.length - 1; i > 0; i--) {
                    let payload = messages[i].get('payload');
                    if (payload.rating) {
                        code[1] += `<li data-id="rating" data-message-id="${messages[i].id}"><i class="sb-icon sb-icon-${payload.rating == 1 ? 'like' : 'dislike'}"></i><span>${sb_('User rating')}</span><label>${sb_(payload.rating == 1 ? 'Helpful' : 'Not helpful')}</label></li>`;
                        break;
                    }
                }
            }
            if (SB_ACTIVE_AGENT.user_type != 'admin') {
                exclude.push('token');
            }
            for (var key in user.details) {
                if (!exclude.includes(key)) {
                    code[0] += this.profileRow(key, user.get(key), key == 'id' ? 'User ID' : key);
                }
            }
            if (user.isExtraEmpty() && is_extra) {
                SBF.ajax({
                    function: 'get-user-extra',
                    user_id: user.id
                }, (response) => {
                    for (var i = 0; i < response.length; i++) {
                        user.setExtra(response[i].slug, response[i]);
                    }
                    return this.populate(user, profile_area, false);
                });
            } else {
                for (var key in user.extra) {
                    let info = user.getExtra(key);
                    code[['os', 'ip', 'browser'].includes(key) ? 2 : 0] += this.profileRow(key, info.value, info.name);
                }
                let is_wrap = profile_area.hasClass('sb-profile-list');
                profile_area.html(`${is_wrap ? '' : '<div class="sb-profile-list">'}<ul class="ul-user">${code[0]}</ul>${code[1] ? `<div class="sb-title">${sb_('Conversation')}</div><ul class="ul-conversation">${code[1]}</ul>` : ''}${code[2] ? `<div class="sb-title">${sb_('Technology')}</div><ul class="ul-technology">${code[2]}</ul></div>${is_wrap ? '' : '</div>'}` : ''}`);
                collapse(profile_area, 145);
                SBF.event('SBUserLoaded', user);
            }
        },

        profileRow: function (key, value, name = key, extra = false, extra_2 = false) {
            if (!value) return '';
            let icons = { id: 'user', full_name: 'user', email: 'envelope', phone: 'phone', user_type: 'user', last_activity: 'calendar', creation_time: 'calendar', token: 'shuffle', currency: 'currency', location: 'marker', country: 'marker', address: 'marker', city: 'marker', postal_code: 'marker', browser: 'desktop', os: 'desktop', current_url: 'next', timezone: 'clock' };
            let icon = `<i class="sb-icon sb-icon-${key in icons ? icons[key] : 'plane'}"></i>`;
            let lowercase;
            let image = false;
            switch (key) {
                case 'last_activity':
                case 'creation_time':
                    value = SBF.beautifyTime(value);
                    break;
                case 'user_type':
                    value = SBF.slugToString(value);
                    break;
                case 'country':
                case 'country_code':
                case 'language':
                case 'browser_language':
                    let flag = value;
                    if (value == 'ar' && (key == 'language' || key == 'browser_language')) {
                        flag = 'arc';
                    }
                    image = `flags/${flag.toLowerCase()}.png`;
                    break;
                case 'browser':
                    lowercase = value.toLowerCase();
                    if (lowercase.includes('chrome')) {
                        image = 'devices/chrome.svg';
                    } else if (lowercase.includes('edge')) {
                        image = 'devices/edge.svg';
                    } else if (lowercase.includes('firefox')) {
                        image = 'devices/firefox.svg';
                    } else if (lowercase.includes('opera')) {
                        image = 'devices/opera.svg';
                    } else if (lowercase.includes('safari')) {
                        image = 'devices/safari.svg';
                    }
                    break;
                case 'os':
                    lowercase = value.toLowerCase();
                    if (lowercase.includes('windows')) {
                        image = 'devices/windows.svg';
                    } else if (lowercase.includes('mac') || lowercase.includes('apple') || lowercase.includes('ipad') || lowercase.includes('iphone')) {
                        image = 'devices/apple.svg';
                    } else if (lowercase.includes('android')) {
                        image = 'devices/android.svg';
                    } else if (lowercase.includes('linux')) {
                        image = 'devices/linux.svg';
                    } else if (lowercase.includes('ubuntu')) {
                        image = 'devices/ubuntu.svg';
                    }
                    break;
                case 'conversation-source':
                    image = `apps/${(extra ? extra : value).toLowerCase()}.svg`;
                    break;
                case 'location':
                    image = 'apps/google-maps.svg';
                    break;
                case 'current_url':
                    value = urlStrip(value);
                    break;
            }
            return `<li data-id="${key}"${extra ? ` data-extra="${extra}"` : ''}${extra_2 ? ` data-extra-2="${extra_2}"` : ''}>${image ? `<img src="${SB_URL}/media/${image}" />` : icon}<span>${sb_(SBF.slugToString(name))}</span><label>${value}</label></li>`;
        },

        // Populate profile edit box
        populateEdit: function (user, profile_edit_area) {
            profile_edit_area.find('.sb-details .sb-input').each((i, element) => {
                this.set(element, user.details[$(element).attr('id')]);
            });
            profile_edit_area.find('.sb-additional-details .sb-input').each((i, element) => {
                let key = $(element).attr('id');
                if (key in user.extra) {
                    this.set(element, user.extra[key].value);
                } else {
                    this.set(element, '');
                }
            });
        },

        // Clear the profile edit area
        clear: function (profile_edit_area) {
            SBForm.clear(profile_edit_area);
        },

        // Check for errors on user input
        errors: function (profile_edit_area) {
            return SBForm.errors(profile_edit_area.find('.sb-details'));
        },

        // Display a error message
        showErrorMessage: function (profile_edit_area, message) {
            SBForm.showErrorMessage(profile_edit_area, message);
        },

        // Agents data area
        agentData: function () {
            let code = `<div class="sb-title">${sb_('Feedback rating')}</div><div class="sb-rating-area sb-loading"></div>`;
            let area = profile_box.find('.sb-agent-area');
            area.html(code);
            SBF.ajax({
                function: 'get-rating'
            }, (response) => {
                if (response[0] == 0 && response[1] == 0) {
                    code = `<p class="sb-no-results">${sb_('No ratings yet.')}</p>`;
                } else {
                    let total = response[0] + response[1];
                    let positive = response[0] * 100 / total;
                    let negative = response[1] * 100 / total;
                    code = `<div><div>${sb_('Helpful')}</div><span data-count="${response[0]}" style="width: ${Math.round(positive * 2)}px"></span><div>${positive.toFixed(2)} %</div></div><div><div>${sb_('Not helpful')}</div><span data-count="${response[1]}" style="width: ${Math.round(negative * 2)}px"></span><div>${negative.toFixed(2)} %</div></div><p class="sb-rating-count">${total} ${sb_('Ratings')}</p>`;
                }
                area.find('.sb-rating-area').html(code).sbLoading(false);
            });
        },

        boxClasses: function (box, user_type = false) {
            $(box).removeClass('sb-type-admin sb-type-agent sb-type-lead sb-type-user sb-type-visitor').addClass(`${user_type != false ? `sb-type-${user_type}` : ''} sb-agent-${SB_ACTIVE_AGENT.user_type}`);
        },

        updateRequiredFields: function (user_type) {
            let agent = SBF.isAgent(user_type);
            profile_edit_box.find('#password input').prop('required', agent);
            profile_edit_box.find('#email input').prop('required', agent);
        }
    }

    /* 
    * ----------------------------------------------------------
    * Admin
    * ----------------------------------------------------------
    */

    var SBAdmin = {

        infoBottom: function (text, type = false) {
            var card = admin.find('.sb-info-card');
            if (!type) {
                card.removeClass('sb-info-card-error sb-info-card-warning sb-info-card-info');
                clearTimeout(timeout);
                timeout = setTimeout(() => { card.sbActive(false) }, 5000);
            } else if (type == 'error') {
                card.addClass('sb-info-card-error');
            } else {
                card.addClass('sb-info-card-info');
            }
            card.html(`<h3>${sb_(text)}</h3>`).sbActive(true);
        },

        infoPanel: function (text, type = 'info', onConfirm = false, id = '', title = '', scroll = false, skip = false, onCancel = false) {
            if (skip && onConfirm) {
                return onConfirm();
            }
            let box = admin.find('.sb-dialog-box').attr('data-type', type);
            let p = box.find('p');
            box.attr('id', id).setClass('sb-scroll-area', scroll).css('height', scroll ? (parseInt($(window).height()) - 200) + 'px' : '');
            box.find('.sb-title').html(title && title.includes('icon-') ? `<i class="sb-${title}"></i>` : title ? sb_(title) : (type == 'alert' ? '<i class="sb-icon-info"></i>' : ''));
            p.html((type == 'alert' ? sb_('Are you sure?') + ' ' : '') + sb_(text));
            box.sbActive(true).css({ 'margin-top': (box.outerHeight() / -2) + 'px', 'margin-left': (box.outerWidth() / -2) + 'px' });
            overlay.sbActive(true);
            alertOnConfirmation = onConfirm;
            alertOnCancel = onCancel;
            setTimeout(() => { SBAdmin.open_popup = box }, 500);
        },

        genericPanel: function (id, title, content, buttons = [], attrs = '', scroll = false) {
            let buttons_code = '';
            let cnt = admin.find('#sb-generic-panel');
            for (var i = 0; i < buttons.length; i++) {
                buttons[i] = isString(buttons[i]) || buttons[i] instanceof String ? [buttons[i], false] : buttons[i];
                buttons_code += `<a id="sb-${SBF.stringToSlug(buttons[i][0])}" class="sb-btn${buttons[i][1] ? ` sb-icon` : ``}">${buttons[i][1] ? `<i class="sb-icon-${buttons[i][1]}"></i>` : ``} ${sb_(buttons[i][0])}</a>`;
            }
            cnt.html(`<div class="sb-lightbox sb-${id}-box"${attrs}><div class="sb-info"></div><div class="sb-top-bar"><div>${sb_(title)}</div>
                        <div>
                            ${buttons_code}
                            <a class="sb-close sb-btn-icon sb-btn-red">
                                <i class="sb-icon-close"></i>
                            </a>
                        </div>
                    </div>
                    <div class="sb-main${scroll ? ' sb-scroll-area' : ''}">
                        ${content}
                    </div>
             </div>`);
            cnt.find('> div').sbShowLightbox();
        },

        activeUser: function (value) {
            if (typeof value == ND) {
                return window.sb_current_user;
            } else {
                window.sb_current_user = value;
            }
        },

        loadingGlobal: function (show = true, is_overlay = true) {
            admin.find('.sb-loading-global').sbActive(show);
            if (is_overlay) {
                overlay.sbActive(show);
                $('body').setClass('sb-lightbox-active', show);
            }
        },

        loading: function (element) {
            if ($(element).sbLoading()) {
                return true;
            }
            $(element).sbLoading(true);
            return false;
        },

        collapse(target, max_height) {
            target = $(target);
            let content = target.find('> div, > ul');
            content.css({ height: '', 'max-height': '' });
            target.find('.sb-collapse-btn').remove();
            if (target.hasClass('sb-collapse')) {
                if ($(content).prop('scrollHeight') > max_height) {
                    target.sbActive(true).attr('data-height', max_height);
                    target.append(`<a class="sb-btn-text sb-collapse-btn">${sb_('View more')}</a>`);
                    content.css({ height: max_height + 'px', 'max-height': max_height + 'px' });
                } else {
                    content.attr('style', '');
                }
            };
        },

        open_popup: false,
        must_translate: false,
        is_logout: false,
        conversations: SBConversations,
        users: SBUsers,
        settings: SBSettings,
        profile: SBProfile,
        apps: SBApps
    }
    window.SBAdmin = SBAdmin;

    /*
    * ----------------------------------------------------------
    * Init
    * ----------------------------------------------------------
    */

    $(document).ready(function () {

        admin = $('.sb-admin');
        header = admin.find('> .sb-header');
        conversations_area = admin.find('.sb-area-conversations');
        conversation_area = conversations_area.find('.sb-conversation');
        conversations_area_list = conversations_area.find('.sb-conversation .sb-list');
        conversations_admin_list = conversations_area.find('.sb-admin-list');
        conversations_admin_list_ul = conversations_admin_list.find('.sb-scroll-area ul');
        conversations_filters = conversations_admin_list.find('.sb-select');
        conversations_user_details = conversations_area.find('.sb-user-details');
        users_area = admin.find('.sb-area-users');
        users_table = users_area.find('.sb-table-users');
        users_table_menu = users_area.find('.sb-menu-users');
        users_filters = users_area.find('.sb-filter-btn .sb-select');
        profile_box = admin.find('.sb-profile-box');
        profile_edit_box = admin.find('.sb-profile-edit-box');
        settings_area = admin.find('.sb-area-settings');
        automations_area = settings_area.find('.sb-automations-area');
        conditions_area = automations_area.find('.sb-conditions');
        automations_area_select = automations_area.find(' > .sb-select');
        automations_area_nav = automations_area.find(' > .sb-tab > .sb-nav > ul');
        reports_area = admin.find('.sb-area-reports');
        articles_area = admin.find('.sb-area-articles');
        articles_content = articles_area.find('.sb-content-articles');
        articles_content_categories = articles_area.find('.sb-content-categories');
        articles_category_parent_select = admin.find('#article-parent-categories');
        articles_category_select = admin.find('#article-categories');
        saved_replies = conversations_area.find('.sb-replies');
        overlay = admin.find('.sb-lightbox-overlay');
        SITE_URL = typeof SB_URL != ND ? SB_URL.substr(0, SB_URL.indexOf('-content') - 3) : '';
        woocommerce_products_box = conversations_area.find('.sb-woocommerce-products');
        woocommerce_products_box_ul = woocommerce_products_box.find(' > div > ul');
        notes_panel = conversations_area.find('.sb-panel-notes');
        tags_panel = conversations_area.find('.sb-panel-tags');
        attachments_panel = conversations_area.find('.sb-panel-attachments');
        direct_message_box = admin.find('.sb-direct-message-box');
        wp_admin = SBApps.is('wordpress') && $('.wp-admin').length;
        chatbot_training_panel = admin.find('.sb-dialogflow-intent-box');
        suggestions_area = conversations_area.find('.sb-editor > .sb-suggestions');
        open_ai_button_rewrite = conversations_area.find('.sb-btn-open-ai');
        select_departments = conversations_area.find('#conversation-department');
        upload_input = admin.find('.sb-upload-form-admin .sb-upload-files');
        chatbot_area = admin.find('.sb-area-chatbot');
        chatbot_files_table = chatbot_area.find('#sb-table-chatbot-files');
        chatbot_website_table = chatbot_area.find('#sb-table-chatbot-website');
        chatbot_qea_repeater = chatbot_area.find('#sb-chatbot-qea');
        chatbot_playground_editor = chatbot_area.find('.sb-playground-editor');
        chatbot_playground_history_panel = chatbot_area.find('.sb-playground-history');
        chatbot_playground_area = chatbot_area.find('.sb-playground .sb-scroll-area');
        flows_area = chatbot_area.find('[data-id="flows"] > .sb-content');
        flows_nav = chatbot_area.find('#sb-flows-nav');
        editor_textarea = conversations_area.find('.sb-editor textarea');

        // Browser history
        window.onpopstate = function () {
            admin.sbHideLightbox();
            if (responsive && conversations_area.sbActive() && conversation_area.sbActive()) {
                SBConversations.mobileCloseConversation();
            }
            if (SBF.getURL('user')) {
                if (!users_area.sbActive()) {
                    header.find('#sb-users').click();
                }
                SBProfile.show(SBF.getURL('user'));
            } else if (SBF.getURL('area')) {
                header.find('#sb-' + SBF.getURL('area')).click();
            } else if (SBF.getURL('conversation')) {
                if (!conversations_area.sbActive()) {
                    header.find('#sb-conversations').click();
                }
                SBConversations.openConversation(SBF.getURL('conversation'));
            } else if (SBF.getURL('setting')) {
                if (!settings_area.sbActive()) {
                    header.find('#sb-settings').click();
                }
                settings_area.find('#tab-' + SBF.getURL('setting')).click();
            } else if (SBF.getURL('report')) {
                if (!reports_area.sbActive()) {
                    header.find('#sb-reports').click();
                }
            }
        };

        if (SBF.getURL('area')) {
            setTimeout(() => { header.find('#sb-' + SBF.getURL('area')).click() }, 300);
        }

        // Installation
        if (typeof SB_ADMIN_SETTINGS == ND) {
            let area = admin.find('.sb-intall');
            let url = window.location.href.replace('/admin', '').replace('.php', '').replace(/#$|\/$/, '');
            $(admin).on('click', '.sb-submit-installation', function () {
                if (loading(this)) return;
                let message = false;
                let account = area.find('#first-name').length;
                if (SBForm.errors(area)) {
                    message = account ? 'All fields are required. Minimum password length is 8 characters. Be sure you\'ve entered a valid email.' : 'All fields are required.';
                } else {
                    if (account && area.find('#password input').val() != area.find('#password-check input').val()) {
                        message = 'The passwords do not match.';
                    } else {
                        SBF.cookie('S' + 'A_' + 'VGCKMENS', 0, 0, 'delete');
                        if (url.includes('?')) {
                            url = url.substr(0, url.indexOf('?'));
                        }
                        $.ajax({
                            method: 'POST',
                            url: url + '/include/ajax.php',
                            data: {
                                function: 'installation',
                                details: $.extend(SBForm.getAll(area), { url: url })
                            }
                        }).done((response) => {
                            if (isString(response)) {
                                response = JSON.parse(response);
                            }
                            response = response[1];
                            if (response && !response.error) {
                                SBF.cookie('SA_' + 'VGCKMENS', response.cv, 30, 'set');
                                setTimeout(() => {
                                    window.location.href = url + '/admin.php?refresh=true';
                                }, 1000);
                                return;
                            } else {
                                message = response.error ? response.error : response;
                            }
                            if (message !== false) {
                                SBForm.showErrorMessage(area, message);
                                $('html, body').animate({ scrollTop: 0 }, 500);
                            }
                            $(this).sbLoading(false);
                        });
                    }
                }
                if (message !== false) {
                    SBForm.showErrorMessage(area, message);
                    $('html, body').animate({ scrollTop: 0 }, 500);
                    $(this).sbLoading(false);
                }
            });
            fetch('h' + 'ttp' + 's' + ':' + '/' + '/boar' + 'd.sup' + 'port/s' + 'ynch/index.p' + 'hp?site=' + encodeURI(url.split('?')[0]));
            return;
        }

        // Initialization
        if (!admin.length) {
            return;
        }
        loadingGlobal();
        admin.removeAttr('style');
        if (isPWA()) {
            admin.addClass('sb-pwa');
        }
        if (localhost) {
            clearCache();
        }
        if (admin.find(' > .sb-rich-login').length) {
            return;
        }
        SBF.storage('notifications-counter', []);
        SBConversations.message_drafts = SBF.storage('message-drafts') ? SBF.storage('message-drafts') : {};
        if (SB_ADMIN_SETTINGS.pusher) {
            SBPusher.active = true;
            SBPusher.init(() => {
                SBPusher.presence(1, () => {
                    SBUsers.updateUsersActivity();
                });
                SBPusher.event('update-conversations', () => {
                    SBConversations.update();
                }, 'agents');
                SBPusher.event('set-agent-status', (response) => {
                    if (response.agent_id == SB_ACTIVE_AGENT.id) {
                        SBUsers.setActiveAgentStatus(response.status == 'online');
                        away_mode = false;
                    }
                }, 'agents');
                initialization();
            });
        } else {
            initialization();
            setInterval(function () {
                SBUsers.updateUsersActivity();
            }, 10000);
        }
        SBUsers.table_extra = users_table.find('th[data-extra]').map(function () { return $(this).attr('data-field') }).get();
        if (typeof SB_CLOUD_FREE != ND && SB_CLOUD_FREE) {
            setTimeout(() => { location.reload() }, 3600000);
        }

        // Dark & Light mode
        if (SBF.storage('dark-mode')) {
            SBF.loadResource(SB_URL + '/css/dark.css');
        }
        $(header).find('.sb-menu li:last-child, .sb-mobile li:last-child').before(`<li data-value="${SBF.storage('dark-mode') ? 'light' : 'dark'}-mode">${sb_(SBF.storage('dark-mode') ? 'Light mode' : 'Dark mode')}</li>`);

        $(header).on('click', '[data-value="dark-mode"], [data-value="light-mode"]', function () {
            let is_dark_mode = $(this).attr('data-value') == 'dark-mode';
            if (is_dark_mode) {
                SBF.loadResource(SB_URL + '/css/dark.css');
            } else {
                document.getElementById('sb-darkcss').remove();
            }
            SBF.storage('dark-mode', is_dark_mode);
            $(this).attr('data-value', is_dark_mode ? 'light-mode' : 'dark-mode').html(sb_(is_dark_mode ? 'Light mode' : 'Dark mode'));
        });

        // On Support Board close
        $(window).on('beforeunload', function () {
            if (activeUser()) {
                $.ajax({ method: 'POST', url: SB_AJAX_URL, data: { function: 'on-close' } });
            }
        });

        // Keyboard shortcuts
        $(window).keydown(function (e) {
            let code = e.which;
            let valid = false;
            active_keydown = code;
            if ([13, 27, 32, 37, 38, 39, 40, 46, 90].includes(code)) {
                if (admin.find('.sb-dialog-box').sbActive()) {
                    let target = admin.find('.sb-dialog-box');
                    switch (code) {
                        case 46:
                        case 27:
                            target.find('.sb-cancel').click();
                            break;
                        case 32:
                        case 13:
                            target.find(target.attr('data-type') != 'info' ? '.sb-confirm' : '.sb-close').click();
                            break;
                    }
                    valid = true;
                } else if ([38, 40, 46, 90].includes(code) && conversations_area.sbActive() && !admin.find('.sb-lightbox').sbActive()) {
                    let is_editor_focus = editor_textarea.is(':focus');
                    if (code == 46) {
                        if (is_editor_focus || e.target.tagName == 'INPUT') {
                            return;
                        }
                        let target = conversations_area.find(' > div > .sb-conversation');
                        target.find('.sb-top [data-value="' + (target.attr('data-conversation-status') == 3 ? 'delete' : 'archive') + '"]').click();
                        valid = true;
                    } else if (e.ctrlKey) {
                        let target = conversations_admin_list_ul.find('.sb-active');
                        if (code == 40) {
                            target.next().click();
                        } else if (code == 38) {
                            target.prev().click();
                        } else if (code == 90 && is_editor_focus && SBConversations.previous_editor_text) {
                            editor_textarea.val(SBConversations.previous_editor_text);
                            SBConversations.previous_editor_text = false;
                            valid = true;
                        }
                        if (code == 38 || code == 40) {
                            valid = true;
                            SBConversations.scrollTo();
                        }
                    }
                } else if ([37, 39].includes(code) && users_area.sbActive() && admin.find('.sb-lightbox').sbActive()) {
                    let target = users_table.find(`[data-user-id="${activeUser().id}"]`);
                    target = code == 39 ? target.next() : target.prev();
                    if (target.length) {
                        admin.sbHideLightbox();
                        SBProfile.show(target.attr('data-user-id'));
                    }
                    valid = true;
                } else if (code == 27 && admin.find('.sb-lightbox').sbActive()) {
                    admin.sbHideLightbox();
                    valid = true;
                } else if (code == 46) {
                    let target = admin.find('.sb-search-btn.sb-active');
                    if (target.length) {
                        target.find('i').click();
                        valid = true;
                    }
                } else if (code == 13 && chatbot_area.find('.sb-playground-editor textarea').is(':focus')) {
                    chatbot_area.find('.sb-playground-editor [data-value="send"]').click();
                    valid = true;
                }
                if (valid) {
                    e.preventDefault();
                }
            }
        });

        $(window).keyup(function (e) {
            active_keydown = false;
        });

        // Check if the admin is active
        $(document).on('click keydown mousemove', function () {
            SBF.debounce(() => {
                if (!SBChat.tab_active) {
                    SBF.visibilityChange();
                }
                SBChat.tab_active = true;
                clearTimeout(active_interval);
                active_interval = setTimeout(() => {
                    SBChat.tab_active = false
                }, 10000);
            }, '#3', 8000);
            if (!responsive && SB_ADMIN_SETTINGS.away_mode) {
                SBF.debounce(() => {
                    if (away_mode) {
                        SBUsers.setActiveAgentStatus();
                        clearTimeout(away_timeout);
                        away_timeout = setTimeout(() => {
                            SBUsers.setActiveAgentStatus(false);
                        }, 600000);
                    }
                }, '#4', 558000);
            }
        });

        // Autosave drafts
        setInterval(() => {
            if (active_admin_area == 'conversations' && SBChat.conversation) {
                let text = editor_textarea.val().trim();
                if (SBConversations.message_drafts[SBChat.conversation.id] != text) {
                    SBConversations.message_drafts[SBChat.conversation.id] = text;
                    SBF.storage('message-drafts', SBConversations.message_drafts);
                }
            }
        }, 5000);

        // Updates and apps
        let messages = [sb_('Please go to Settings > Miscellaneous and enter the Envato Purchase Code of Support Board.'), `${sb_('Your license key is expired. Please purchase a new license')} <a href="https://board.support/shop/{R}" target="_blank">${sb_('here')}</a>.`];
        $(header).on('click', '.sb-version', function () {
            let box = admin.find('.sb-updates-box');
            SBF.ajax({
                function: 'get-versions'
            }, (response) => {
                let code = '';
                let names = { sb: 'Support Board', slack: 'Slack', dialogflow: 'Artificial Intelligence', tickets: 'Tickets', woocommerce: 'Woocommerce', ump: 'Ultimate Membership Pro', perfex: 'Perfex', whmcs: 'WHMCS', aecommerce: 'Active eCommerce', messenger: 'Messenger', whatsapp: 'WhatsApp', armember: 'ARMember', telegram: 'Telegram', viber: 'Viber', line: 'LINE', wechat: 'WeChat', zalo: 'Zalo', twitter: 'Twitter', zendesk: 'Zendesk', martfury: 'Martfury', opencart: 'OpenCart', zalo: 'Zalo' };
                let updates = false;
                for (var key in response) {
                    if (SBApps.is(key)) {
                        let updated = SB_VERSIONS[key] == response[key];
                        if (!updated) {
                            updates = true;
                        }
                        code += `<div class="sb-input"><span>${names[key]}</span><div${updated ? ' class="sb-green"' : ''}>${updated ? sb_('You are running the latest version.') : sb_('Update available! Please update now.')} ${sb_('Your version is')} V ${SB_VERSIONS[key]}.</div></div>`;
                    }
                }
                if (updates) {
                    box.find('.sb-update').removeClass('sb-hide');
                } else {
                    box.find('.sb-update').addClass('sb-hide');
                }
                loadingGlobal(false);
                box.find('.sb-main').prepend(code);
                box.sbShowLightbox();
            });
            loadingGlobal();
            box.sbActive(false);
            box.find('.sb-input').remove();
        });

        $(admin).on('click', '.sb-updates-box .sb-update', function () {
            if (loading(this)) return;
            let box = admin.find('.sb-updates-box');
            SBF.ajax({
                function: 'update',
                domain: SB_URL
            }, (response) => {
                let error = '';
                if (SBF.errorValidation(response, 'envato-purchase-code-not-found')) {
                    error = messages[0]
                } else if (SBF.errorValidation(response)) {
                    error = SBF.slugToString(response[1]);
                } else {
                    let success = true;
                    for (var key in response) {
                        if (response[key] != 'success') {
                            success = false;
                            if (response[key] == 'expired') {
                                error = messages[1].replace('{R}', key);
                            }
                            if (response[key] == 'license-key-not-found') {
                                error = sb_('License key for the {R} app missing. Add it in Settings > Apps.').replace('{R}', SBF.slugToString(key.replace('dialogflow', 'Artificial Intelligence')));
                            }
                            break;
                        }
                    }
                    if (!success && !error) {
                        error = JSON.stringify(response);
                    }
                }
                clearCache();
                if (!error) {
                    infoBottom('Update completed.');
                    location.reload();
                } else {
                    SBForm.showErrorMessage(box, error);
                }
                $(this).sbLoading(false);
            });
        });

        setTimeout(function () {
            let last = SBF.storage('last-update-check');
            let today_arr = [today.getMonth(), today.getDate()];
            if (SB_ADMIN_SETTINGS.cloud) {
                return;
            }
            if (last == false || today_arr[0] != last[0] || (today_arr[1] > (last[1] + 10))) {
                SBF.storage('last-update-check', today_arr);
                if (SB_ADMIN_SETTINGS.auto_updates) {
                    SBF.ajax({
                        function: 'update',
                        domain: SB_URL
                    }, (response) => {
                        if (!isString(response) && !Array.isArray(response)) {
                            infoBottom('Automatic update completed. Reload the admin area to apply the update.');
                            clearCache();
                        }
                    });
                } else if (SB_ACTIVE_AGENT.user_type == 'admin') {
                    SBF.ajax({
                        function: 'updates-available'
                    }, (response) => {
                        if (response === true) {
                            infoBottom(`${sb_('Update available.')} <span onclick="$(\'.sb-version\').click()">${sb_('Click here to update now')}</span>`, 'info');
                        }
                    });
                }
            }
            if (!SBF.cookie('' + 'SA' + '_' + 'V' + 'GC' + 'KM' + 'EN' + 'S')) {
                setTimeout(() => { $('body').html('') }, 10000);
            }
        }, 1000);

        $(admin).on('click', '.sb-apps > div:not(.sb-disabled)', function () {
            let box = admin.find('.sb-app-box');
            let app_name = $(this).data('app');
            let is_cloud = SB_ADMIN_SETTINGS.cloud;
            let is_active = SBApps.is(app_name) && (!is_cloud || SB_CLOUD_ACTIVE_APPS.includes(app_name));
            let ga = '?utm_source=plugin&utm_medium=admin_area&utm_campaign=plugin';
            if (!is_cloud) {
                SBF.ajax({
                    function: 'app-get-key',
                    app_name: app_name
                }, (response) => {
                    box.find('input').val(response);
                });
            }
            box.setClass('sb-active-app', is_active);
            box.find('input').val('');
            box.find('.sb-top-bar > div:first-child').html($(this).find('h2').html());
            box.find('p').html($(this).find('p').html());
            box.attr('data-app', app_name);
            box.find('.sb-btn-app-setting').sbActive(is_active);
            box.find('.sb-btn-app-puchase').attr('href', 'https://board.support/shop/' + app_name + ga);
            box.find('.sb-btn-app-details').attr('href', (is_cloud ? WEBSITE_URL : 'https://board.support/') + app_name + ga);
            box.sbShowLightbox();
        });

        $(admin).on('click', '.sb-app-box .sb-activate', function () {
            let box = admin.find('.sb-app-box');
            let key = box.find('input').val();
            let app_name = box.attr('data-app');
            if (key || SB_ADMIN_SETTINGS.cloud) {
                if (loading(this)) return;
                SBF.ajax({
                    function: 'app-activation',
                    app_name: app_name,
                    key: key
                }, (response) => {
                    if (SBF.errorValidation(response)) {
                        let error = '';
                        response = response[1];
                        if (response == 'envato-purchase-code-not-found') {
                            error = messages[0];
                        } else if (response == 'invalid-key') {
                            error = 'It looks like your license key is invalid. If you believe this is an error, please contact support.';
                        } else if (response == 'expired') {
                            error = messages[1].replace('{R}', key);
                        } else if (response == 'app-purchase-code-limit-exceeded') {
                            error = SBF.slugToString(app_name) + ' app purchase code limit exceeded.';
                        } else {
                            error = response;
                        }
                        SBForm.showErrorMessage(box, error);
                        $(this).sbLoading(false);
                    } else {
                        infoBottom('Activation complete! Page reload in progress...');
                        setTimeout(function () {
                            location.reload();
                        }, 1000);
                    }
                });
            } else {
                SBForm.showErrorMessage(box, 'Please insert the license key.');
            }
        });

        $(admin).on('click', '.sb-app-box .sb-btn-app-setting', function () {
            settings_area.find('#tab-' + $(this).closest('[data-app]').attr('data-app')).click();
            admin.sbHideLightbox();
        });

        // Desktop and flash notifications
        if (typeof Notification !== ND && (SB_ADMIN_SETTINGS.desktop_notifications == 'all' || SB_ADMIN_SETTINGS.desktop_notifications == 'agents') && !SB_ADMIN_SETTINGS.push_notifications) {
            SBConversations.desktop_notifications = true;
        }

        if (['all', 'agents'].includes(SB_ADMIN_SETTINGS.flash_notifications)) {
            SBConversations.flash_notifications = true;
        }

        // Cron jobs
        if (today.getDate() != SBF.storage('admin-clean')) {
            setTimeout(function () {
                SBF.ajax({ function: 'cron-jobs' });
                SBF.storage('admin-clean', today.getDate());
            }, 10000);
        }

        // Collapse button
        $(admin).on('click', '.sb-collapse-btn', function () {
            let active = $(this).sbActive();
            let height = active ? $(this).parent().data('height') + 'px' : '';
            $(this).html(sb_(active ? 'View more' : 'Close'));
            $(this).parent().find('> div, > ul').css({ 'height': height, 'max-height': height });
            $(this).sbActive(!active);
        });

        // Close lightbox popup
        $(admin).on('click', '.sb-popup-close', function () {
            admin.sbHideLightbox();
        });

        /*
        * ----------------------------------------------------------
        * Responsive
        * ----------------------------------------------------------
        */

        if (responsive) {

            conversations_user_details.find('> .sb-scroll-area').prepend('<div class="sb-profile"><img><span class="sb-name"></span></div>');

            $(admin).on('click', '.sb-menu-mobile > i', function () {
                $(this).toggleClass('sb-active');
                SBAdmin.open_popup = $(this).parent();
            });

            $(admin).on('click', '.sb-menu-mobile a', function () {
                $(this).closest('.sb-menu-mobile').find(' > i').sbActive(false);
            });

            $(admin).on('click', '.sb-menu-wide,.sb-nav', function () {
                $(this).toggleClass('sb-active');
            });

            $(admin).on('click', '.sb-menu-wide > ul > li, .sb-nav > ul > li', function (e) {
                let menu = $(this).parent().parent();
                menu.find('li').sbActive(false);
                menu.find('> div:not(.sb-menu-wide):not(.sb-btn)').html($(this).html());
                menu.sbActive(false);
                if (menu.find('> .sb-menu-wide').length) {
                    menu.closest('.sb-scroll-area').scrollTop(menu.next()[0].offsetTop - (admin.hasClass('sb-header-hidden') ? 70 : 130));
                }
                e.preventDefault();
                return false;
            });

            $(admin).find('.sb-admin-list .sb-scroll-area, main > div > .sb-scroll-area, .sb-area-settings > .sb-tab > .sb-scroll-area, .sb-area-reports > .sb-tab > .sb-scroll-area, [data-id="playground"], .sb-area-chatbot>.sb-tab').on('scroll', function () {
                let scroll = $(this).scrollTop();
                if (scrolls.last < (scroll - 10) && scrolls.header) {
                    admin.addClass('sb-header-hidden');
                    scrolls.header = false;
                } else if (scrolls.last > (scroll + 10) && !scrolls.header && !scrolls.always_hidden) {
                    admin.removeClass('sb-header-hidden');
                    scrolls.header = true;
                }
                scrolls.last = scroll;
            });

            $(admin).on('click', '.sb-search-btn i,.sb-filter-btn i', function () {
                if ($(this).parent().sbActive()) {
                    admin.addClass('sb-header-hidden');
                    scrolls.always_hidden = true;
                } else {
                    scrolls.always_hidden = false;
                    if (conversations_admin_list_ul.parent().scrollTop() < 10) {
                        admin.removeClass('sb-header-hidden');
                    }
                }
            });

            $(admin).on('click', '#sb-close-filters-btn', function () {
                scrolls.always_hidden = false;
                admin.removeClass('sb-header-hidden');
            });

              $(admin).on('click', '#sb-close-filters-btn', function () {
                scrolls.always_hidden = false;
                admin.removeClass('sb-header-hidden');
            });

            $(admin).on('click', '.sb-playground-history .sb-close', function () {
                $(this).parent().sbActive(false);
            });

            $(users_table).find('th:first-child').html(sb_('Order by'));

            $(users_table).on('click', 'th:first-child', function () {
                $(this).parent().toggleClass('sb-active');
            });

            // Touch move
            document.addEventListener('touchstart', (e) => {
                touchmove_x = e.changedTouches[0].clientX;
                touchmove_y = e.changedTouches[0].clientY;
            }, false);

            document.addEventListener('touchend', () => {
                touchEndEvent();
            }, false);

            document.addEventListener('touchmove', (e) => {
                var x_up = e.changedTouches[0].clientX;
                var x_diff = touchmove_x - x_up;
                var y_up = e.changedTouches[0].clientY;
                var y_diff = touchmove_y - y_up;
                if (Math.abs(x_diff) > Math.abs(y_diff)) {
                    var target_sub = [];
                    touchmove = conversations_area.sbActive() ? [conversations_admin_list_ul.find('.sb-active'), conversations_area_list, 1] : [users_table.find(`[data-user-id="${activeUser().id}"]`), profile_box, 2];
                    if (x_diff > 150) {

                        // Left
                        if (touchmove[2] == 1) {
                            touchmove[0].next().click();
                        } else {
                            target_sub = touchmove[0].next();
                        }
                        touchEndEvent();
                    } else if (x_diff < -150) {

                        // Right
                        if (touchmove[2] == 1) {
                            touchmove[0].prev().click();
                        } else {
                            target_sub = touchmove[0].prev();
                        }
                        touchEndEvent();
                    }
                    if (touchmove[2] == 2 && target_sub.length) {
                        admin.sbHideLightbox();
                        SBProfile.show(target_sub.attr('data-user-id'));
                    }
                    if (x_diff > 80 || x_diff < -80) {
                        touchmove[1].css('transform', 'translateX(' + (x_diff * -1) + 'px)');
                        touchmove[1].addClass('sb-touchmove');
                    }
                }
            }, false);
        } else {
            if (!SB_ADMIN_SETTINGS.hide_conversation_details) {
                conversations_user_details.sbActive(true);
            } else {
                conversations_area.find('.sb-menu-mobile [data-value="panel"]').sbActive(true);
            }
        }

        if ($(window).width() < 913) {
            $(conversations_area).on('click', '> .sb-btn-collapse', function () {
                $(this).toggleClass('sb-active');
                conversations_area.find('.sb-admin-list').toggleClass('sb-active');
            });
        }

        /*
        * ----------------------------------------------------------
        * Left nav
        * ----------------------------------------------------------
        */

        $(header).on('click', ' .sb-admin-nav a, #sb-settings', function () {
            active_admin_area = $(this).attr('id').substr(3);
            SBAdmin.active_admin_area = active_admin_area;
            header.find('.sb-admin-nav a, #sb-settings').sbActive(false);
            admin.find(' > main > div').sbActive(false);
            admin.find('.sb-area-' + active_admin_area).sbActive(true);
            $(this).sbActive(true);
            SBF.deactivateAll();
            switch (active_admin_area) {
                case 'conversations':
                    if (!responsive && !SBF.getURL('conversation')) {
                        SBConversations.clickFirst();
                    }
                    SBConversations.update();
                    SBConversations.startRealTime();
                    SBUsers.stopRealTime();
                    break;
                case 'users':
                    SBUsers.startRealTime();
                    SBConversations.stopRealTime();
                    if (!SBUsers.init) {
                        loadingGlobal();
                        users_pagination = 1;
                        users_pagination_count = 1;
                        SBUsers.get((response) => {
                            SBUsers.populate(response);
                            SBUsers.updateMenu();
                            SBUsers.init = true;
                            SBUsers.datetime_last_user = SBF.dateDB('now');
                            loadingGlobal(false);
                        });
                    }
                    break;
                case 'settings':
                    if (!SBSettings.init) {
                        loadingGlobal();
                        SBF.ajax({
                            function: 'get-all-settings'
                        }, (response) => {
                            if (response) {
                                let translations = response['external-settings-translations'];
                                if (response['slack-agents']) {
                                    let code = '';
                                    for (const key in response['slack-agents'][0]) {
                                        code += `<div id="${key}" data-type="select" class="multi-input-select"><select><option value="${response['slack-agents'][0][key][0]}" selected></option></select></div>`;
                                    }
                                    settings_area.find('#slack-agents .input').html(code);
                                }
                                SBSettings.translations.translations = Array.isArray(translations) && !translations.length ? {} : translations;
                                delete response['external-settings-translations'];
                                for (var key in response) {
                                    SBSettings.set(key, response[key]);
                                }
                            }
                            if (SBF.getURL('refresh_token')) {
                                admin.find('#google-refresh-token input').val(SBF.getURL('refresh_token'));
                                SBSettings.save();
                                infoBottom('Synchronization completed.');
                                admin.find('#google')[0].scrollIntoView();
                            }
                            settings_area.find('textarea').each(function () {
                                $(this).autoExpandTextarea();
                                $(this).manualExpandTextarea();
                            });
                            settings_area.find('[data-setting] .sb-language-switcher-cnt').each(function () {
                                $(this).sbLanguageSwitcher(SBSettings.translations.getLanguageCodes($(this).closest('[data-setting]').attr('id')), 'settings');
                            });
                            SBSettings.init = true;
                            loadingGlobal(false);
                            if (response && !SB_ADMIN_SETTINGS.cloud) {
                                SBSettings.visibility(0, response['push-notifications'] && response['push-notifications'][0]['push-notifications-provider'][0] == 'pusher');
                            }
                            SBSettings.visibility(1, response['messenger'] ? response['messenger'][0]['messenger-sync-mode'][0] != 'manual' : true);
                            SBSettings.visibility(2, response['open-ai'] ? response['open-ai'][0]['open-ai-mode'][0] != 'assistant' : true);
                            SBSettings.visibility(3, response['header-type'] ? response['header-type'][0] == 'agents' : true);
                            SBF.event('SBSettingsLoaded', response);
                        });
                    }
                    SBUsers.stopRealTime();
                    SBConversations.stopRealTime();
                    break;
                case 'reports':
                    if (reports_area.sbLoading()) {
                        SBSettings.loadDatePicker(() => {
                            $.getScript(SB_URL + '/vendor/chart.min.js', () => {
                                reports_area.find('#sb-date-picker').daterangepicker(SBSettings.getDatePickerSettings(false, false, true)).val(moment().subtract(29, 'days').format('DD-MM-YYYY') + ' - ' + moment().format('DD-MM-YYYY'));
                                $('.ranges li').eq(3).click();
                                SBReports.initReport('conversations');
                                reports_area.sbLoading(false);
                            });
                        });
                    }
                    SBUsers.stopRealTime();
                    SBConversations.stopRealTime();
                    break;
                case 'articles':
                    let nav = articles_area.find('.sb-menu-wide li').eq(0);
                    if (articles_area.sbLoading()) {
                        nav.sbActive(true).next().sbActive(false);
                        SBF.ajax({
                            function: 'init-articles-admin'
                        }, (response) => {
                            SBArticles.categories.list = response[1];
                            SBArticles.translations.list = response[2];
                            SBArticles.page_url = response[3];
                            SBArticles.is_url_rewrite = response[4];
                            SBArticles.cloud_chat_id = response[5];
                            SBArticles.populate(response[0]);
                            SBArticles.populate(response[1], true);
                            SBArticles.categories.update();
                            articles_area.sbLoading(false);
                        });
                    } else {
                        nav.click();
                    }
                    SBUsers.stopRealTime();
                    SBConversations.stopRealTime();
                    break;
                case 'chatbot':
                    if (chatbot_files_table.sbLoading()) {
                        SBApps.openAI.init();
                    }
                    SBApps.openAI.troubleshoot();
            }
            let url_area = SBF.getURL('area');
            if (url_area != active_admin_area && ((active_admin_area == 'conversations' && !SBF.getURL('conversation')) || (active_admin_area == 'users' && !SBF.getURL('user')) || (active_admin_area == 'settings' && !SBF.getURL('setting')) || (active_admin_area == 'reports' && !SBF.getURL('report')) || (active_admin_area == 'articles' && !SBF.getURL('article')) || (active_admin_area == 'chatbot' && !SBF.getURL('chatbot')))) {
                pushState('?area=' + active_admin_area);
            }
        });

        $(header).on('click', '.sb-profile', function () {
            $(this).next().toggleClass('sb-active');
        });

        $(header).on('click', '[data-value="logout"],.logout', function () {
            SBAdmin.is_logout = true;
            SBF.ajax({ function: 'on-close' });
            SBUsers.stopRealTime();
            SBConversations.stopRealTime();
            setTimeout(() => { SBF.logout() }, 300);
        });

        $(header).on('click', '[data-value="edit-profile"],.edit-profile', function () {
            loadingGlobal();
            let user = new SBUser({ id: SB_ACTIVE_AGENT.id });
            user.update(() => {
                activeUser(user);
                conversations_area.find('.sb-board').addClass('sb-no-conversation');
                conversations_admin_list_ul.find('.sb-active').sbActive(false);
                SBProfile.showEdit(user);
            });
        });

        $(header).on('click', '[data-value="status"]', function () {
            let is_offline = !$(this).hasClass('sb-online');
            SBUsers.setActiveAgentStatus(is_offline);
            away_mode = is_offline;
        });

        $(header).find('.sb-account').setProfile(SB_ACTIVE_AGENT['full_name'], SB_ACTIVE_AGENT['profile_image']);

        /*
        * ----------------------------------------------------------
        * Conversations area
        * ----------------------------------------------------------
        */

        $(editor_textarea).on('focus input click', function () {
            editor_textarea.parent().parent().addClass('sb-focus');
        });

        $(editor_textarea).on('focusout', function () {
            editor_textarea.parent().parent().removeClass('sb-focus');
        });

        // Open the conversation clicked on the left menu
        $(conversations_admin_list_ul).on('click', 'li', function () {
            if (active_keydown == 17) {
                $(this).sbActive(!$(this).sbActive());
            } else {
                SBConversations.openConversation($(this).attr('data-conversation-id'), $(this).attr('data-user-id'), false);
                SBF.deactivateAll();
            }
        });

        // Open the user conversation clicked on the bottom right area or user profile box
        $(admin).on('click', '.sb-user-conversations li', function () {
            SBConversations.openConversation($(this).attr('data-conversation-id'), activeUser().id, $(this).attr('data-conversation-status'));
        });

        // Archive, delete or restore conversations
        $(conversations_area).on('click', '.sb-top ul a', function () {
            let status_code;
            let selected_conversations = SBConversations.getSelectedConversations();
            let selected_conversations_length = selected_conversations.length;
            let multi_selection = selected_conversations_length > 1;
            let message = multi_selection ? 'All the selected conversations will be ' : 'The conversation will be ';
            let value = $(this).attr('data-value');
            let on_success = (response, action) => {
                let success = response.includes('.txt');
                $(this).sbLoading(false);
                if (action == 'email') {
                    actioninfoBottom(success ? sb_('Transcript sent to user\'s email.') + ' <a href="' + response + '" target="_blank">' + sb_('View transcript') + '</a>' : 'Transcript sending error: ' + response, success ? '' : 'error');
                }
            }
            switch (value) {
                case 'inbox':
                    status_code = 1;
                    message += 'restored.';
                    break;
                case 'archive':
                    message += 'archived.';
                    status_code = 3;
                    break;
                case 'delete':
                    message += 'deleted.';
                    status_code = 4;
                    break;
                case 'empty-trash':
                    status_code = 5;
                    message = 'All conversations in the trash (including their messages) will be deleted permanently.'
                    break;
                case 'transcript':
                    let action = $(this).attr('data-action');
                    if (action == 'email' && (!activeUser() || !activeUser().get('email'))) {
                        action = '';
                    }
                    SBConversations.transcript(selected_conversations[0].id, selected_conversations[0].user_id, action, (response) => on_success(response, action));
                    loading(this);
                    break;
                case 'read':
                    status_code = 1;
                    message += 'marked as read.';
                    break;
                case 'unread':
                    status_code = 2;
                    message += 'marked as unread.';
                    break;
                case 'panel':
                    $([conversations_user_details, this]).toggleClass('sb-active');
                    break;
            }
            if (status_code) {
                infoPanel(message, 'alert', function () {
                    let active_conversations_filter = conversations_filters.eq(0).find('p').attr('data-value');
                    let last_conversation_id = selected_conversations[selected_conversations_length - 1].id;
                    for (var i = 0; i < selected_conversations_length; i++) {
                        let conversation = selected_conversations[i];
                        let is_active_conversation = SBChat.conversation && SBChat.conversation.id == conversation.id
                        SBF.ajax({
                            function: 'update-conversation-status',
                            conversation_id: conversation.id,
                            status_code: status_code
                        }, () => {
                            let conversation_li = getListConversation(conversation.id);
                            if ([0, 3, 4].includes(status_code)) {
                                for (var j = 0; j < conversations.length; j++) {
                                    if (conversations[j].id == conversation.id) {
                                        conversations[j].set('status_code', status_code);
                                        break;
                                    }
                                }
                            }
                            if (status_code == 3) {
                                if (SB_ADMIN_SETTINGS.close_message) {
                                    SBF.ajax({ function: 'close-message', conversation_id: conversation.id });
                                    if (SB_ADMIN_SETTINGS.close_message_transcript) {
                                        SBConversations.transcript(conversation.id, conversation.user_id, 'email', (response) => on_success(response));
                                    }
                                }
                                if (SB_ADMIN_SETTINGS.rating && is_active_conversation && SBChat.conversation.get('source')) {
                                    SBF.ajax({ function: 'rating-message', conversation_id: conversation.id });
                                }
                            }
                            if ([0, 1, 2].includes(status_code)) {
                                conversation_li.attr('data-conversation-status', status_code);
                                SBConversations.updateMenu();
                            }
                            if (is_active_conversation && SBApps.is('slack') && [3, 4].includes(status_code)) {
                                SBF.ajax({ function: 'archive-slack-channels', conversation_user_id: SBChat.conversation.get('user_id') });
                            }
                            if ((active_conversations_filter == 0 && [3, 4].includes(status_code)) || (active_conversations_filter == 3 && [0, 1, 2, 4].includes(status_code)) || (active_conversations_filter == 4 && status_code != 4)) {
                                let previous = false;
                                SBConversations.updateMenu();
                                if (is_active_conversation) {
                                    previous = conversation_li.prev();
                                    SBChat.conversation = false;
                                }
                                conversation_li.remove();
                                if (conversation.id == last_conversation_id) {
                                    SBConversations.clickFirst(previous);
                                }
                            }
                            if (active_conversations_filter == 4 && status_code == 5) {
                                conversations_admin_list_ul.find('li').remove();
                                SBConversations.updateMenu();
                                SBConversations.clickFirst();
                            }
                        });
                        if (is_active_conversation) {
                            SBChat.conversation.set('status_code', status_code);
                            SBConversations.setReadIcon(status_code);
                        }
                    }
                });
            }
        });

        // Saved replies
        SBF.ajax({
            function: 'saved-replies'
        }, (response) => {
            let code = `<p class="sb-no-results">${sb_('No saved replies found. Add new saved replies via Settings > Admin.')}</p>`;
            if (Array.isArray(response)) {
                if (response.length && response[0]['reply-name']) {
                    code = '';
                    saved_replies_list = response;
                    for (var i = 0; i < response.length; i++) {
                        code += `<li><div>${response[i]['reply-name']}</div><div>${response[i]['reply-text'].replace(/\\n/g, '\n')}</div></li>`;
                    }
                }
            }
            saved_replies.find('.sb-replies-list > ul').html(code).sbLoading(false);
        });

        $(conversations_area).on('click', '.sb-btn-saved-replies', function () {
            saved_replies.sbTogglePopup(this);
            if (saved_replies_list.length > 10) {
                saved_replies.find('.sb-search-btn').sbActive(true).find('input').get(0).focus();
            }
        });

        $(saved_replies).on('click', '.sb-replies-list li', function () {
            SBChat.insertText($(this).find('div:last-child').text().replace(/\\n/g, '\n'));
            SBF.deactivateAll();
            admin.removeClass('sb-popup-active');
        });

        $(saved_replies).on('input', '.sb-search-btn input', function () {
            saved_reply_search($(this).val().toLowerCase());
        });

        $(saved_replies).on('click', '.sb-search-btn i', function () {
            SBF.searchClear(this, () => { saved_reply_search('') });
        });

        $(admin).on('click', '.sb-btn-open-ai', function () {
            if (!SBChat.conversation || loading(this)) return;
            let is_editor = $(this).hasClass('sb-btn-open-ai-editor');
            let textarea = is_editor ? editor_textarea : chatbot_training_panel.find('textarea');
            SBApps.openAI.rewrite(textarea.val(), (response) => {
                $(this).sbLoading(false);
                textarea.val(is_editor ? '' : response);
                if (is_editor) {
                    SBChat.insertText(response);
                }
            });
        });

        $(saved_replies).on('click', '.sb-add-saved-reply', function () {
            $(this).find('i').toggleClass('sb-icon-close');
            saved_replies.find('.sb-replies-add-area').toggleClass('sb-active');
        });

        $(saved_replies).on('click', '.sb-replies-add-area a', function () {
            let values = saved_replies.find('.sb-replies-add-area input').map(function () {
                return $(this).val();
            });
            if (!values[0] || !values[1] || loading(this)) {
                return;
            }
            SBF.ajax({
                function: 'add-saved-reply',
                name: values[0],
                text: values[1]
            }, (response) => {
                $(this).sbLoading(false);
                saved_replies.find('.sb-add-saved-reply i').removeClass('sb-icon-close');
                saved_replies.find('.sb-replies-add-area').sbActive(false);
                if (response === true) {
                    if (!saved_replies_list) {
                        saved_replies_list = [];
                        saved_replies.find('.sb-no-results').remove();
                    }
                    saved_replies_list.push({ 'reply-name': values[0], 'reply-text': values[1] });
                    saved_replies.find('.sb-replies-list > ul').prepend(`<li><div>${values[0]}</div><div>${values[1].replace(/\\n/g, '\n')}</div></li>`);
                }
            });
        });

        // Pagination for conversations
        $(conversations_admin_list).find('.sb-scroll-area').on('scroll', function () {
            if (!is_busy && !SBConversations.is_search && scrollPagination(this, true) && pagination_count) {
                let parent = conversations_area.find('.sb-admin-list');
                let filters = SBConversations.filters();
                is_busy = true;
                parent.append('<div class="sb-loading-global sb-loading"></div>');
                SBF.ajax({
                    function: 'get-conversations',
                    pagination: pagination,
                    status_code: filters[0],
                    department: filters[1],
                    source: filters[2],
                    tag: filters[3],
                    agent_id: filters[4]
                }, (response) => {
                    setTimeout(() => { is_busy = false }, 500);
                    pagination_count = response.length;
                    if (pagination_count) {
                        let code = '';
                        for (var i = 0; i < pagination_count; i++) {
                            let conversation = new SBConversation([new SBMessage(response[i])], response[i]);
                            code += SBConversations.getListCode(conversation);
                            conversations.push(conversation);
                        }
                        pagination++;
                        conversations_admin_list_ul.append(code);
                    }
                    parent.find(' > .sb-loading').remove();
                    SBF.event('SBAdminConversationsLoaded', { conversations: response });
                });
            }
        });

        // Event: message deleted
        $(document).on('SBMessageDeleted', function () {
            let last_message = SBChat.conversation.getLastMessage();
            if (last_message != false) {
                conversations_admin_list_ul.find('li.sb-active p').html(last_message.message);
            } else {
                conversations_admin_list_ul.find('li.sb-active').remove();
                SBConversations.clickFirst();
                SBConversations.scrollTo();
            }
        });

        // Event: message sent
        $(document).on('SBMessageSent', function (e, response) {
            let conversation_id = response.conversation_id;
            let message_part = sb_('Error. Message not sent to');
            let conversation = response.conversation;
            let user = response.user;
            let reply_to = response.payload && response.payload.reply ? response.payload.reply : false;
            delete SBConversations.message_drafts[conversation_id];
            SBF.storage('message-drafts', SBConversations.message_drafts);
            if (response.conversation_status_code) {
                SBConversations.updateMenu();
            }
            if (SBApps.messenger.check(conversation)) {
                let last_user_message = conversation.getLastUserMessage();
                if (last_user_message && last_user_message.payload() && last_user_message.payload().cid) {
                    SBApps.messenger.sendComment(last_user_message.payload().cid, conversation.get('extra'), response.message, response.message_id, conversation.get('source') == 'ig', (response) => {
                        for (var i = 0; i < response.length; i++) {
                            if (response[i] && response[i].error) {
                                infoPanel(message_part + ' Messenger: ' + response[i].error.message, 'info', false, 'error-fb');
                            }
                        }
                    });
                } else {
                    SBApps.messenger.send(user.getExtra('facebook-id').value, conversation.get('extra'), response.message, response.attachments, response.message_id, response.message_id, reply_to, (response) => {
                        for (var i = 0; i < response.length; i++) {
                            if (response[i] && response[i].error) {
                                infoPanel(message_part + ' Messenger: ' + response[i].error.message, 'info', false, 'error-fb');
                            }
                        }
                    });
                }
            }
            if (SBApps.whatsapp.check(conversation)) {
                SBApps.whatsapp.send(SBApps.whatsapp.activeUserPhone(user), response.message, response.attachments, conversation.get('extra'), reply_to, response.message_id, (response) => {
                    if (response.ErrorCode || (response.meta && !response.meta.success)) {
                        infoPanel(message_part + ' WhatsApp: ' + ('ErrorCode' in response ? response.errorMessage : response.meta.developer_message), 'info', false, 'error-wa');
                    }
                });
            }
            if (SBApps.telegram.check(conversation)) {
                SBApps.telegram.send(conversation.get('extra'), response.message, response.attachments, conversation_id, reply_to, response.message_id, (response) => {
                    if (!response || !response.ok) {
                        infoPanel(message_part + ' Telegram: ' + JSON.stringify(response), 'info', false, 'error-tg');
                    }
                });
            }
            if (SBApps.viber.check(conversation)) {
                SBApps.viber.send(user.getExtra('viber-id').value, response.message, response.attachments, (response) => {
                    if (!response || response.status_message != 'ok') {
                        infoPanel(message_part + ' Viber: ' + JSON.stringify(response), 'info', false, 'error-vb');
                    }
                });
            }
            if (SBApps.zalo.check(conversation)) {
                SBApps.zalo.send(user.getExtra('zalo-id').value, response.message, response.attachments, (response) => {
                    if (response && response.error.error) {
                        infoPanel(message_part + ' Zalo: ' + response.error.message ? response.error.message : response.message, 'info', false, 'error-za');
                    }
                });
            }
            if (SBApps.twitter.check(conversation)) {
                SBApps.twitter.send(user.getExtra('twitter-id').value, response.message, response.attachments, (response_2) => {
                    if (response_2 && !response_2.event) {
                        infoPanel(JSON.stringify(response_2), 'info', false, 'error-tw');
                    } else if (response.attachments.length > 1) {
                        infoBottom('Only the first attachment was sent to Twitter.');
                    }
                });
            }
            if (SBApps.line.check(conversation)) {
                SBApps.line.send(user.getExtra('line-id').value, response.message, response.attachments, conversation_id, (response) => {
                    if (response.error) {
                        infoPanel(message_part + ' LINE: ' + JSON.stringify(response), 'info', false, 'error-ln');
                    }
                });
            }
            if (SBApps.wechat.check(conversation)) {
                SBApps.wechat.send(user.getExtra('wechat-id').value, response.message, response.attachments, (response) => {
                    if (!response || response.errmsg != 'ok') {
                        infoPanel(message_part + ' WeChat: ' + JSON.stringify(response), 'info', false, 'error-wc');
                    }
                });
            }
            if (SB_ADMIN_SETTINGS.smart_reply) {
                suggestions_area.html('');
            }
            if (SB_ADMIN_SETTINGS.assign_conversation_to_agent && SBF.null(conversation.get('agent_id'))) {
                SBConversations.assignAgent(conversation_id, SB_ACTIVE_AGENT.id, () => {
                    if (SBChat.conversation.id == conversation_id) {
                        SBChat.conversation.set('agent_id', SB_ACTIVE_AGENT.id);
                        $(conversations_area).find('#conversation-agent > p').attr('data-value', SB_ACTIVE_AGENT.id).html(SB_ACTIVE_AGENT.full_name);
                    }
                });
            }
        });

        // Event: new message of active chat conversation received
        $(document).on('SBNewMessagesReceived', function (e, response) {
            let messages = response.messages;
            for (var i = 0; i < messages.length; i++) {
                let message = messages[i];
                let payload = message.payload();
                let agent = SBF.isAgent(message.get('user_type'));
                setTimeout(function () {
                    conversation_area.find('.sb-top .sb-status-typing').remove();
                }, 300);
                if (SBAdmin.must_translate) {
                    let message_html = conversation_area.find(`[data-id="${message.id}"]`);
                    let message_original = payload['original-message'] ? payload['original-message'] : false;
                    if (message_original) {
                        message_html.replaceWith(message.getCode());
                        conversation_area.find(`[data-id="${message.id}"] .sb-menu`).prepend(`<li data-value="translation">${sb_('View translation')}</li>`);
                        if (SB_ADMIN_SETTINGS.smart_reply) {
                            SBApps.dialogflow.smartReply(SBF.escape(message_original));
                        }
                    } else if (message.message) {
                        SBApps.dialogflow.translate([message.message], SB_ADMIN_SETTINGS.active_agent_language, (response_2) => {
                            if (response_2) {
                                message.payload('translation', response_2[0]);
                                message.payload('translation-language', SB_ADMIN_SETTINGS.active_agent_language);
                                message_html.replaceWith(message.getCode());
                                conversation_area.find(`[data-id="${message.id}"] .sb-menu`).prepend(`<li data-value="original">${sb_('View original message')}</li>`);
                            }
                            if (SB_ADMIN_SETTINGS.smart_reply) {
                                SBApps.dialogflow.smartReply(response_2[0]);
                            }
                            getListConversation(response.conversation_id).find('p').html(response_2[0]);
                        }, [message.id], SBChat.conversation.id);
                    }
                } else if (SB_ADMIN_SETTINGS.smart_reply) {
                    SBApps.dialogflow.smartReply(message.message);
                }
                if (payload) {
                    if (payload.department) {
                        SBConversations.setActiveDepartment(payload.department);
                    }
                    if (payload.agent) {
                        SBConversations.setActiveAgent(payload.agent);
                    }
                }
                if ('ErrorCode' in payload || (payload.errors && payload.errors.length)) {
                    infoPanel('Error. Message not sent to WhatsApp. Error message: ' + (payload.ErrorCode ? payload.ErrorCode : payload.errors[0].title));
                }
                if ('whatsapp-templates' in payload) {
                    infoBottom(`Message sent as text message.${'whatsapp-template-fallback' in payload ? ' The user has been notified via WhatsApp Template notification.' : ''}`);
                }
                if ('whatsapp-template-fallback' in payload && !('whatsapp-templates' in payload)) {
                    infoBottom('The user has been notified via WhatsApp Template notification.');
                }
                if (!agent && SBChat.conversation.id == response.conversation_id && !SBChat.user_online) {
                    SBUsers.setActiveUserStatus();
                }
            }
            SBConversations.update();
        });

        // Event: new conversation created 
        $(document).on('SBNewConversationCreated', function () {
            SBConversations.update();
        });

        // Event: email notification sent
        $(document).on('SBEmailSent', function () {
            infoBottom(`The user has been notified by email.`);
        });

        // Event: SMS notification sent
        $(document).on('SBSMSSent', function () {
            infoBottom('The user has been notified by text message.');
        });

        // Event: Message notifications
        $(document).on('SBNotificationsSent', function (e, response) {
            infoBottom(`The user ${response.includes('cron') ? 'will be' : 'has been'} notified by email${response.includes('sms') ? ' and text message' : ''}.`);
        });

        // Event: user typing status change
        $(document).on('SBTyping', function (e, response) {
            SBConversations.typing(response);
        });

        // Conversations search
        $(conversations_admin_list).on('input', '.sb-search-btn input', function () {
            SBConversations.search(this);
        });

        $(conversations_area).on('click', '.sb-admin-list .sb-search-btn i', function () {
            SBF.searchClear(this, () => { SBConversations.search($(this).next()) });
        });

        // Conversations filter
        $(conversations_filters).on('click', 'li', function (e) {
            let parent = conversations_admin_list_ul.parent();
            if (loading(parent)) {
                e.preventDefault()
                return false;
            }
            setTimeout(() => {
                let filters = SBConversations.filters();
                pagination = 1;
                pagination_count = 1;
                SBF.ajax({
                    function: 'get-conversations',
                    status_code: filters[0],
                    department: filters[1],
                    source: filters[2],
                    tag: filters[3],
                    agent_id: filters[4]
                }, (response) => {
                    SBConversations.populateList(response);
                    conversation_area.attr('data-conversation-status', filters[0]);
                    if (response.length) {
                        if (!responsive) {
                            if (SBChat.conversation) {
                                let conversation = getListConversation(SBChat.conversation.id);
                                if (conversation.length) {
                                    conversation.sbActive(true);
                                } else if (filters[0] == SBChat.conversation.status_code) {
                                    conversations_admin_list_ul.prepend(SBConversations.getListCode(SBChat.conversation));
                                } else {
                                    SBConversations.clickFirst();
                                }
                            } else {
                                SBConversations.clickFirst();
                            }
                            SBConversations.scrollTo();
                        }
                    } else {
                        conversations_area.find('.sb-board').addClass('sb-no-conversation');
                        SBChat.conversation = false;
                    }
                    $(this).closest('.sb-filter-btn').attr('data-badge', conversations_filters.slice(1).toArray().reduce((acc, filter) => acc + !!$(filter).find('li.sb-active').data('value'), 0));
                    parent.sbLoading(false);
                });
            }, 100);
        });

        // Display the user details box
        $(conversations_area).on('click', '.sb-user-details .sb-profile,.sb-top > a', function () {
            let user_id = conversations_admin_list_ul.find('.sb-active').attr('data-user-id');
            if (activeUser().id != user_id) {
                activeUser(users[user_id]);
            }
            SBProfile.show(activeUser().id);
        });

        // Right profile list methods
        $(admin).on('click', '.sb-panel-conversation-details li', function () {
            let label = $(this).find('label');
            let label_value = label.html();
            switch ($(this).attr('data-id')) {
                case 'location':
                    let location = label_value.replace(', ', '+');
                    infoPanel('<iframe src="https://maps.google.com/maps?q=' + location + '&output=embed"></iframe>', 'map');
                    break;
                case 'timezone':
                    SBF.getLocationTimeString(activeUser().extra, (response) => {
                        loadingGlobal(false);
                        infoPanel(response);
                    });
                    break;
                case 'current_url':
                    window.open('//' + (SBF.null(label.attr('data-value')) ? label_value : label.attr('data-value')));
                    break;
                case 'conversation-source':
                    let source = ($(this).attr('data-extra') ? $(this).attr('data-extra') : label_value).toLowerCase();
                    let extra = $(this).attr('data-extra-2');
                    if (source == 'whatsapp' && activeUser().getExtra('phone')) {
                        window.open('https://wa.me/' + SBApps.whatsapp.activeUserPhone());
                    } else if (source == 'facebook') {
                        window.open('https://www.facebook.com/' + (extra ? extra : 'messages/t/' + SBChat.conversation.get('extra')));
                    } else if (source == 'instagram') {
                        window.open('https://www.instagram.com/' + (extra ? extra : 'direct/inbox/'));
                    } else if (source == 'twitter') {
                        window.open('https://twitter.com/messages/');
                    }
                    break;
                case 'wp-id':
                    window.open(window.location.href.substr(0, window.location.href.lastIndexOf('/')) + '/user-edit.php?user_id=' + activeUser().getExtra('wp-id').value);
                    break;
                case 'envato-purchase-code':
                    loadingGlobal();
                    SBF.ajax({
                        function: 'envato',
                        purchase_code: label_value
                    }, (response) => {
                        let code = '';
                        if (response && response.item) {
                            response.name = response.item.name;
                            for (var key in response) {
                                if (isString(response[key]) || !isNaN(response[key])) {
                                    code += `<b>${SBF.slugToString(key)}</b> ${response[key]} <br>`;
                                }
                            }
                            loadingGlobal(false);
                            infoPanel(code, 'info', false, 'sb-envato-box');
                        } else {
                            infoBottom(SBF.slugToString(response));
                        }
                    });
                    break;
                case 'email':
                case 'cc':
                    if (SBChat.conversation && SBChat.conversation.get('source') == 'em') {
                        let cc = SBChat.conversation.get('extra').split(',');
                        let code = `<div data-type="repeater" class="sb-setting sb-type-repeater"><div class="input"><div class="sb-repeater">`;
                        for (var i = 0; i < cc.length; i++) {
                            code += `<div class="repeater-item"><div><input data-id="cc" type="text" value="${cc[i]}"></div><i class="sb-icon-close"></i></div>`;
                        }
                        code += `</div><div class="sb-btn sb-repeater-add sb-icon"><i class="sb-icon-plus"></i>${sb_('Add new item')}</div></div></div>`;
                        SBAdmin.genericPanel('cc', 'Manage CC', code, ['Save changes'], '', true);
                    }
                    break;
            }
        });

        $(conversations_user_details).on('click', '.sb-user-details-close', function () {
            conversations_area.find('.sb-menu-mobile [data-value="panel"]').click().sbActive(true);
        });

        // Dialogflow
        $(chatbot_training_panel).on('click', '.sb-intent-add [data-value="add"]', function () {
            chatbot_training_panel.find('> div > .sb-type-text').last().after('<div class="sb-setting sb-type-text"><input type="text"></div>');
        });

        $(chatbot_training_panel).on('click', '.sb-intent-add [data-value="previous"],.sb-intent-add [data-value="next"]', function () {
            let input = chatbot_training_panel.find('.sb-first input');
            let message = input.val();
            let next = $(this).attr('data-value') == 'next';
            let messages = SBChat.conversation.getUserMessages();
            let messages_length = messages.length;
            for (var i = 0; i < messages_length; i++) {
                if (messages[i].message == message && ((next && i < (messages_length - 1)) || (!next && i > 0))) {
                    i = i + (next ? 1 : -1);
                    input.val(messages[i].message);
                    chatbot_training_panel.attr('data-message-id', messages[i].id);
                    SBApps.openAI.generateQuestions(messages[i].message);
                    break;
                }
            }
        });

        $(chatbot_training_panel).on('click', '.sb-send', function () {
            SBApps.dialogflow.trainingPanel.submit(this);
        });

        $(chatbot_training_panel).on('input', '.sb-search-btn input', function () {
            SBApps.dialogflow.trainingPanel.search($(this).val());
        });

        $(chatbot_training_panel).on('click', '.sb-search-btn i', function () {
            SBF.searchClear(this, () => { SBApps.dialogflow.trainingPanel.search($(this).val()) });
        });

        $(chatbot_training_panel).on('click', '#sb-qea-preview', function () {
            SBApps.dialogflow.trainingPanel.preview(chatbot_training_panel.find('#sb-qea-select').val());
        });

        $(chatbot_training_panel).on('change', '#sb-qea-select', function () {
            let qea = $(this).val();
            chatbot_training_panel.find('.sb-bot-response').setClass('sb-disabled', qea).find('textarea').val(qea ? SBApps.dialogflow.trainingPanel.qea[qea][1] : SBApps.dialogflow.trainingPanel.original_response);
        });

        $(chatbot_training_panel).on('change', 'textarea', function () {
            clearTimeout(timeout);
            timeout = setTimeout(() => {
                SBApps.dialogflow.trainingPanel.original_response = chatbot_training_panel.find('textarea').val();
            }, 500);
        });

        // Departments
        $(select_departments).on('click', 'li', function (e) {
            let select = $(this).parent().parent();
            if ($(this).data('id') == select.find(' > p').attr('data-id')) {
                setTimeout(() => { $(this).sbActive(false); }, 100);
                return true;
            }
            if (!SBChat.conversation) {
                $(this).parent().sbActive(false);
                e.preventDefault();
                return false;
            }
            if (!select.sbLoading()) infoPanel(`${sb_('All agents assigned to the new department will be notified. The new department will be')} ${$(this).html()}.`, 'alert', () => {
                let value = $(this).data('id');
                select.sbLoading(true);
                SBConversations.assignDepartment(SBChat.conversation.id, value, () => {
                    SBConversations.setActiveDepartment(value);
                    select.sbLoading(false);
                });
            });
            e.preventDefault();
            return false;
        });

        // Agent assignment
        $(conversations_area).on('click', '#conversation-agent li', function (e) {
            let select = $(this).parent().parent();
            let agent_id = $(this).data('id');
            if (agent_id == select.find(' > p').attr('data-value')) return true;
            if (!SBChat.conversation) {
                $(this).parent().sbActive(false);
                e.preventDefault();
                return false;
            }
            if (!select.sbLoading()) {
                infoPanel(`${sb_('The new agent will be')} ${$(this).html()}.`, 'alert', () => {
                    select.sbLoading(true);
                    let selected_conversations = SBConversations.getSelectedConversations();
                    selected_conversations.forEach(conversation => {
                        SBConversations.assignAgent(conversation.id, agent_id, () => {
                            if (SBChat.conversation && SBChat.conversation.id == conversation.id) {
                                SBConversations.setActiveAgent(agent_id);
                            }
                        });
                    });
                    select.sbLoading(false);
                });
            }
            e.preventDefault();
            return false;
        });

        // Notes and Tags 
        notes_panel.on('click', '> i,.sb-edit-note', function (e) {
            let note = $(this).hasClass('sb-edit-note') ? $(this).closest('[data-id]') : false;
            SBAdmin.genericPanel('notes', note ? 'Edit note' : 'Add new note', `<div class="sb-setting sb-type-textarea"><textarea${note ? ' data-id="' + note.attr('data-id') + '"' : ''} placeholder="${sb_('Write here your note...')}">${note ? note.find('.sb-note-text').html().replace(/<a\s+href="([^"]*)".*?>(.*?)<\/a>/gi, '$1').replaceAll('<br>', '\n') : ''}</textarea></div>`, [[note ? 'Update note' : 'Add note', note ? 'check' : 'plus']]);
            if (SBApps.is('dialogflow') && SB_ADMIN_SETTINGS.note_data_scrape) {
                let options = '';
                for (var key in SB_ADMIN_SETTINGS.note_data_scrape) {
                    options += `<option value="${key}">${SB_ADMIN_SETTINGS.note_data_scrape[key]}</option>`;
                }
                admin.find('#sb-add-note').parent().prepend(`<div id="note-ai-scraping" class="sb-setting sb-type-select"><select><option value="">${sb_('Data scraping')}</option>${options}</select></div>`);
            }
            e.preventDefault();
            return false;
        });

        $(admin).on('change', '#note-ai-scraping select', function () {
            let value = $(this).val();
            if (!value || loading($(this).parent())) {
                return;
            }
            SBF.ajax({
                function: 'data-scraping',
                conversation_id: SBChat.conversation.id,
                prompt_id: value
            }, (response) => {
                if (response && response.error) {
                    console.error(response);
                    return infoBottom(response.error.message, 'error');
                }
                $(this).parent().sbLoading(false);
                let textarea = admin.find('.sb-notes-box textarea');
                textarea.val((textarea.val() + '\n' + response).trim());
            });
        });

        notes_panel.on('click', '.sb-delete-note', function () {
            let item = $(this).parents().eq(1);
            SBConversations.notes.delete(SBChat.conversation.id, item.attr('data-id'), () => {
                item.remove();
            });
        });

        $(admin).on('click', '#sb-add-note, #sb-update-note', function () {
            let textarea = $(this).parent().parents().eq(1).find('textarea');
            let message = textarea.val();
            let note_id = textarea.attr('data-id');
            if (message.length == 0) {
                SBForm.showErrorMessage(admin.find('.sb-notes-box'), 'Please write something...');
            } else {
                if (loading(this)) return;
                message = SBF.escape(message);
                SBConversations.notes.add(SBChat.conversation.id, SB_ACTIVE_AGENT.id, SB_ACTIVE_AGENT.full_name, message, (response) => {
                    if (Number.isInteger(response) || response === true) {
                        $(this).sbLoading(false);
                        admin.sbHideLightbox();
                        if (note_id) {
                            notes_panel.find(`[data-id="${note_id}"]`).remove();
                        }
                        SBConversations.notes.update([{ id: note_id ? note_id : response, conversation_id: SBChat.conversation.id, user_id: SB_ACTIVE_AGENT.id, name: SB_ACTIVE_AGENT['full_name'], message: message }], true);
                        textarea.val('');
                        infoBottom(note_id ? 'Note successfully updated.' : 'New note successfully added.');
                    } else {
                        SBForm.showErrorMessage(response);
                    }
                }, note_id);
            }
        });

        tags_panel.on('click', '> i', function (e) {
            let code = SBConversations.tags.getAll(SBChat.conversation.details.tags);;
            SBAdmin.genericPanel('tags', 'Manage tags', code ? '<div class="sb-tags-cnt">' + code + '</div>' : '<p>' + sb_('Add tags from Settings > Admin > Tags.') + '</p>', ['Save tags']);
            e.preventDefault();
            return false;
        });

        $(admin).on('click', '.sb-tags-cnt > span', function () {
            $(this).toggleClass('sb-active');
        });

        $(admin).on('click', '#sb-add-tag', function () {
            $('<input type="text">').insertBefore(this);
        });

        $(admin).on('click', '#sb-save-tags', function () {
            if (loading(this)) return;
            let tags = admin.find('.sb-tags-box').find('span.sb-active').map(function () {
                return $(this).attr('data-value');
            }).toArray();
            let conversation_id = SBChat.conversation.id;
            SBF.ajax({
                function: 'update-tags',
                conversation_id: conversation_id,
                tags: tags
            }, (response) => {
                $(this).sbLoading(false);
                if (response === true) {
                    SBConversations.tags.update(tags);
                    if (SBChat.conversation && conversation_id == SBChat.conversation.id) {
                        let tag_filter = SBConversations.filters()[3];
                        let conversation_li = getListConversation(conversation_id);
                        SBChat.conversation.set('tags', tags);
                        if (tag_filter && !tags.includes(tag_filter)) {
                            conversation_li.remove();
                            SBConversations.clickFirst();
                        } else if (SB_ADMIN_SETTINGS.tags_show) {
                            let tags_area = conversation_li.find('.sb-tags-area');
                            let code = SBConversations.tags.codeLeft(tags);
                            if (tags_area.length) {
                                tags_area.replaceWith(code);
                            } else {
                                $(code).insertAfter(conversation_li.find('.sb-name'));
                            }
                        }
                    }
                }
                admin.sbHideLightbox();
                infoBottom(response === true ? 'Tags have been successfully updated.' : response);
            });
        });

        // Suggestions
        $(suggestions_area).on('click', 'span', function () {
            SBChat.insertText($(this).text());
            suggestions_area.html('');
        });

        $(suggestions_area).on('mouseover', 'span', function () {
            timeout = setTimeout(() => { $(this).addClass('sb-suggestion-full'); }, 2500);
        });

        $(suggestions_area).on('mouseout', 'span', function () {
            clearTimeout(timeout);
            suggestions_area.find('span').removeClass('sb-suggestion-full');
        });

        // Message menu
        $(conversations_area).on('click', '.sb-list .sb-menu > li', function () {
            let message = $(this).closest('[data-id]');
            let message_id = message.attr('data-id');
            let message_ = SBChat.conversation.getMessage(message_id);
            let message_user_type = message_.get('user_type');
            let value = $(this).attr('data-value');
            switch (value) {
                case 'delete':
                    if (SBChat.user_online) {
                        SBF.ajax({
                            function: 'update-message',
                            message_id: message_id,
                            message: '',
                            attachments: [],
                            payload: { event: 'delete-message' }
                        }, () => {
                            SBChat.conversation.deleteMessage(message_id);
                            message.remove();
                        });
                    } else {
                        SBChat.deleteMessage(message_id);
                    }
                    break;
                case 'translation':
                case 'original':
                    let is_translation = value == 'translation';
                    let keys = ['translation', 'translation-language', 'original-message', 'original-message-language'];
                    let original_payload = keys.map(key => message_.payload(key)).concat(message_.details.message);
                    message_.set('message', is_translation ? message_.payload('translation') || message_.get('message') : message_.payload('original-message') || message_.get('message'));
                    keys.forEach(key => delete message_.details.payload[key]);
                    message.replaceWith(message_.getCode().replace('sb-menu">', `sb-menu"><li data-value="${is_translation ? 'original' : 'translation'}">${sb_(is_translation ? 'View original message' : 'View translation')}</li>`));
                    keys.forEach((key, i) => message_.payload(key, original_payload[i]));
                    message_.details.message = original_payload[4];
                    break;
                case 'bot':
                    SBApps.dialogflow.trainingPanel.show($(this).closest('[data-id]').attr('data-id'));
                    break;
                case 'reply':
                    let is_agent = SBF.isAgent(message_user_type);
                    let text = message_.get('message');
                    if (!text) {
                        message_.attachments.forEach((attachment) => {
                            text += '<i class="sb-icon-clip"></i>' + attachment[0];
                        });
                    }
                    conversations_area.find('.sb-editor [data-reply]').remove();
                    conversations_area.find('.sb-editor').prepend(`<div data-reply="${message_id}"${is_agent ? ' class="sb-reply-color"' : ''}><span>${(is_agent && admin) || (!is_agent && !admin) ? sb_('You') : message_.get('full_name')}</span>${text}<i class="sb-icon-close" onclick="SBChat.cancelReply()"></i></div>`);
                    conversations_area_list.addClass('sb-reply-active');
                    break;
            }
        });

        // Conversations filter
        $(conversations_area).on('click', '.sb-filter-btn i', function () {
            $(this).parent().toggleClass('sb-active');
        });

        $(conversations_area).on('click', '#sb-close-filters-btn', function () {
            conversations_area.find('.sb-filter-btn').sbActive(false);
        });

        $(conversations_area).on('click', '.sb-filter-star', function () {
            $(this).parent().find('li').sbActive(false);
            $(this).parent().find(`li[data-value="${$(this).sbActive() ? '' : $(this).attr('data-value')}"]`).last().sbActive(true).click();
            $(this).toggleClass('sb-active');
        });

        // Attachments filter
        attachments_panel.on('click', '#sb-attachments-filter li', function () {
            let links = attachments_panel.find('a:not(.sb-collapse-btn)');
            let file_type = $(this).attr('data-value');
            links.each(function () {
                $(this).setClass('sb-hide', file_type && SBF.getFileType($(this).attr('href')) != file_type);
            });
            collapse(attachments_panel, 160);
        });

        // CC
        $(admin).on('click', '.sb-cc-box #sb-save-changes', function () {
            let cc = admin.find('.sb-cc-box .repeater-item input').map(function () {
                return $(this).val();
            }).get().join(',');
            loading(this);
            SBF.ajax({
                function: 'update-conversation-extra',
                conversation_id: SBChat.conversation.id,
                extra: cc ? cc : 'NULL'
            }, () => {
                SBChat.conversation.set('extra', cc);
                SBConversations.cc(cc.split(','));
                $(this).sbLoading(false);
                admin.sbHideLightbox();
            });
        });

        // Info messages
        $(conversations_area).on('click', '.sb-info-message-btn', function () {
            let message_id = $(this).closest('.sb-info-message').attr('data-id');
            let message = SBChat.conversation.getMessage(message_id);
            let code = '';
            let title = '';
            let buttons = [];
            let attributes = ' data-message-id="' + message_id + '"';
            switch ($(this).attr('data-id')) {
                case 'call':
                    title = 'WhatsApp Voice Call';
                    code = `<div class="sb-player"><div class="sb-player-btn sb-icon-play"></div><div class="sb-player-speed"><div class="sb-player-speed-number">1</div><div class="sb-icon-close"></div></div><div class="sb-player-time"><span>0:00</span> / <span>${SBF.getMinutesSeconds(message.payload('duration'))}</span></div><div class="sb-player-download sb-icon-arrow-down"></div><audio><source src="${message.payload('call_audio')}" type="audio/mpeg"></audio></div>`;
                    if (message.payload('transcript')) {
                        code += SBApps.openAI.getAudioTranscriptCode(message.payload('transcript'));
                    } else if (SB_ADMIN_SETTINGS.open_ai_chatbot_status === true) {
                        buttons = [['Generate transcript']];
                    }
                    break;
            }
            SBAdmin.genericPanel('call-info', title, code, buttons, attributes, true);
        });

        // Audio player
        $(admin).on('click', '.sb-lightbox .sb-player-btn', function () {
            SBF.audio.play(this, $(this).parent());
        });

        $(admin).on('click', '.sb-lightbox .sb-player-speed', function () {
            SBF.audio.speed(this);
        });

        $(admin).on('click', '.sb-lightbox .sb-player-download', function () {
            SBF.audio.download(this);
        });

        $(admin).on('click', '#sb-generate-transcript', function () {
            if (loading(this)) return;
            let lightbox = $(this).closest('.sb-lightbox');
            const message_id = lightbox.attr('data-message-id');
            SBF.ajax({
                function: 'open-ai-audio-transcript',
                url: SBChat.conversation.getMessage(message_id).payload('call_audio'),
                message_id: message_id
            }, (response) => {
                $(this).sbLoading(false);
                lightbox.find('.sb-main').append(SBApps.openAI.getAudioTranscriptCode(response.segments));
            });
        });

        /*
        * ----------------------------------------------------------
        * Users area
        * ----------------------------------------------------------
        */

        // Open user box by URL
        if (SBF.getURL('user')) {
            header.find('.sb-admin-nav #sb-users').click();
            setTimeout(() => { SBProfile.show(SBF.getURL('user')) }, 500);
        }

        // Checkbox selector
        $(users_table).on('click', 'th :checkbox', function () {
            users_table.find('td :checkbox').prop('checked', $(this).prop('checked'));
        });

        $(users_table).on('click', ':checkbox', function () {
            let button = users_area.find('[data-value="delete"]');
            let button_2 = users_area.find('[data-value="merge_users"]');
            if (users_table.find('td input:checked').length) {
                button.removeAttr('style');
            } else {
                button.hide();
            }
            if (users_table.find('td input:checked').length == 2 && users_table_menu.find('.sb-active').attr('data-type') != 'agent') {
                button_2.removeAttr('style');
            } else {
                button_2.hide();
            }
        });

        // Table menu filter
        $(users_table_menu).on('click', 'li', function () {
            SBUsers.filter($(this).data('type'));
        });

        // Filters
        $(users_filters).on('click', 'li', function () {
            let button = users_filters.closest('.sb-filter-btn');
            setTimeout(() => {
                SBUsers.get((response) => {
                    SBUsers.populate(response);
                });
                button.attr('data-badge', users_filters.toArray().reduce((acc, filter) => acc + !!$(filter).find('li.sb-active').data('value'), 0));
            }, 100);
            button.sbActive(false);
        });

        // Search users
        $(users_area).on('input', '.sb-search-btn input', function () {
            SBUsers.search(this);
        });

        $(users_area).on('click', '.sb-search-btn i', function () {
            SBF.searchClear(this, () => { SBUsers.search($(this).next()) });
        });

        // Sorting
        $(users_table).on('click', 'th:not(:first-child)', function () {
            let direction = $(this).hasClass('sb-order-asc') ? 'DESC' : 'ASC';
            $(this).toggleClass('sb-order-asc');
            $(this).siblings().sbActive(false);
            $(this).sbActive(true);
            SBUsers.sort($(this).data('field'), direction);
        });

        // Pagination for users
        $(users_table).parent().on('scroll', function () {
            if (!is_busy && !SBUsers.search_query && scrollPagination(this, true) && users_pagination_count) {
                is_busy = true;
                users_area.append('<div class="sb-loading-global sb-loading sb-loading-pagination"></div>');
                SBUsers.get((response) => {
                    setTimeout(() => { is_busy = false }, 500);
                    users_pagination_count = response.length;
                    if (users_pagination_count) {
                        let code = '';
                        for (var i = 0; i < users_pagination_count; i++) {
                            let user = new SBUser(response[i], response[i].extra);
                            code += SBUsers.getRow(user);
                            users[user.id] = user;
                        }
                        users_pagination++;
                        users_table.find('tbody').append(code);
                    }
                    users_area.find(' > .sb-loading-pagination').remove();
                }, false, true);
            }
        });

        // Delete user button
        $(profile_edit_box).on('click', '.sb-delete', function () {
            if (SB_ACTIVE_AGENT.id == activeUser().id) {
                return infoBottom('You cannot delete yourself.', 'error');
            }
            infoPanel('This user will be deleted permanently including all linked data, conversations, and messages.', 'alert', function () {
                SBUsers.delete(activeUser().id);
            });
        });

        // Display user box
        $(users_table).on('click', 'td:not(:first-child)', function () {
            SBProfile.show($(this).parent().attr('data-user-id'));
        });

        // Display edit box
        $(profile_box).on('click', '.sb-top-bar .sb-edit', function () {
            SBProfile.showEdit(activeUser());
        });

        // Display new user box
        $(users_area).on('click', '.sb-new-user', function () {
            profile_edit_box.addClass('sb-user-new');
            profile_edit_box.find('.sb-top-bar .sb-profile span').html(sb_('Add new user'));
            profile_edit_box.find('.sb-top-bar .sb-save').html(`<i class="sb-icon-check"></i>${sb_('Add user')}`);
            profile_edit_box.find('input,select,textara').removeClass('sb-error');
            profile_edit_box.removeClass('sb-cloud-admin');
            if (SB_ACTIVE_AGENT.user_type == 'admin') {
                profile_edit_box.find('#user_type').find('select').html(`<option value="user">${sb_('User')}</option><option value="agent">${sb_('Agent')}</option><option value="admin">${sb_('Admin')}</option>`);
            }
            SBProfile.clear(profile_edit_box);
            SBProfile.boxClasses(profile_edit_box);
            SBProfile.updateRequiredFields('user');
            profile_edit_box.sbShowLightbox();
        });

        // Add or update user
        $(profile_edit_box).on('click', '.sb-save', function () {
            if (loading(this)) return;
            let new_user = (profile_edit_box.hasClass('sb-user-new') ? true : false);
            let user_id = profile_edit_box.attr('data-user-id');

            // Get settings
            let settings = SBProfile.getAll(profile_edit_box.find('.sb-details'));
            let settings_extra = SBProfile.getAll(profile_edit_box.find('.sb-additional-details'));
            let output = {};
            $.map(settings, function (value, key) {
                settings[key] = value[0];
            });

            // Errors check
            if (SBProfile.errors(profile_edit_box)) {
                SBProfile.showErrorMessage(profile_edit_box, SBF.isAgent(profile_edit_box.find('#user_type :selected').val()) ? 'First name, last name, password and a valid email are required. Minimum password length is 8 characters.' : (profile_edit_box.find('#password').val().length < 8 ? 'Minimum password length is 8 characters.' : 'First name is required.'));
                $(this).sbLoading(false);
                return;
            }
            if (SB_ACTIVE_AGENT.id == activeUser().id && settings.user_type == 'agent' && SB_ACTIVE_AGENT.user_type == 'admin') {
                SBProfile.showErrorMessage(profile_edit_box, 'You cannot change your status from admin to agent.');
                $(this).sbLoading(false);
                return;
            }
            if (!settings.user_type) {
                settings.user_type = 'user';
            }

            // Save the data
            SBF.ajax({
                function: (new_user ? 'add-user' : 'update-user'),
                user_id: user_id,
                settings: settings,
                settings_extra: settings_extra
            }, (response) => {
                if (SBF.errorValidation(response, 'duplicate-email') || SBF.errorValidation(response, 'duplicate-phone')) {
                    SBProfile.showErrorMessage(profile_edit_box, `This ${SBF.errorValidation(response, 'duplicate-email') ? 'email' : 'phone number'} is already in use.`);
                    $(this).sbLoading(false);
                    return;
                }
                if (new_user) {
                    user_id = response;
                    activeUser(new SBUser({ id: user_id }));
                }
                activeUser().update(() => {
                    users[user_id] = activeUser();
                    if (new_user) {
                        SBProfile.clear(profile_edit_box);
                        SBUsers.update();
                    } else {
                        SBUsers.updateRow(activeUser());
                        if (conversations_area.sbActive()) {
                            SBConversations.updateUserDetails();
                        }
                        if (user_id == SB_ACTIVE_AGENT.id) {
                            SBF.loginCookie(response[1]);
                            SB_ACTIVE_AGENT.full_name = activeUser().name;
                            SB_ACTIVE_AGENT.profile_image = activeUser().image;
                            header.find('.sb-account').setProfile();
                        }
                    }
                    if (new_user) {
                        profile_edit_box.find('.sb-profile').setProfile(sb_('Add new user'));
                    }
                    $(this).sbLoading(false);
                    if (!new_user) {
                        admin.sbHideLightbox();
                    }
                    infoBottom(new_user ? 'New user added' : 'User updated');
                });
                SBF.event('SBUserUpdated', { new_user: new_user, user_id: user_id });
            });
        });

        // Set and unset required visitor fields
        $(profile_edit_box).on('change', '#user_type', function () {
            let value = $(this).find("option:selected").val();
            SBProfile.boxClasses(profile_edit_box, value);
            SBProfile.updateRequiredFields(value);
        });

        // Open a user conversation
        $(profile_box).on('click', '.sb-user-conversations li', function () {
            SBConversations.open($(this).attr('data-conversation-id'), $(this).find('[data-user-id]').attr('data-user-id'));
        });

        // Start a new user conversation
        $(profile_box).on('click', '.sb-start-conversation', function () {
            SBConversations.open(-1, activeUser().id);
            SBConversations.openConversation(-1, activeUser().id);
            if (responsive) {
                SBConversations.mobileOpenConversation();
            }
        });

        // User profile top bar actions
        $(profile_box).on('click', '.sb-top-bar [data-value]', function () {
            let value = $(this).attr('data-value');
            if (value == 'whatsapp-call') {
                if (loading(this)) return;
                SBF.call.start('whatsapp', profile_box.attr('data-user-id'), () => {
                    $(this).sbLoading(false);
                });
            } else {
                SBConversations.showDirectMessageBox(value, [activeUser().id]);
            }
        });

        $(admin).on('click', '#sb-whatsapp-alert-btn', function () {
            SBConversations.showDirectMessageBox('whatsapp', [activeUser().id]);
        });

        // Top icons menu
        $(users_area).on('click', '.sb-top-bar [data-value]', function () {
            let value = $(this).data('value');
            let user_ids = SBUsers.getSelected();
            switch (value) {
                case 'whatsapp':
                    whatsapp_direct_message_box(user_ids);
                    break;
                case 'message':
                case 'custom_email':
                case 'sms':
                    SBConversations.showDirectMessageBox(value, user_ids);
                    break;
                case 'csv':
                    SBUsers.csv();
                    break;
                case 'delete':
                    if (user_ids.includes(SB_ACTIVE_AGENT.id)) {
                        return infoBottom('You cannot delete yourself.', 'error');
                    }
                    infoPanel('All selected users will be deleted permanently including all linked data, conversations, and messages.', 'alert', () => {
                        SBUsers.delete(user_ids);
                        $(this).hide();
                        users_table.find('th:first-child input').prop('checked', false);
                    });
                    break;
                case 'merge_users':
                    infoPanel('The selected users will be merged into one user.', 'alert', () => {
                        let user_ids = users_table.find('td:first-child input:checked').map(function () {
                            return $(this).closest('tr').attr('data-user-id');
                        }).get();
                        SBF.ajax({
                            function: 'merge-users',
                            user_id_1: user_ids[0],
                            user_id_2: user_ids[1]
                        }, (response) => {
                            let user = new SBUser(response, response.details);
                            SBUsers.updateRow(user);
                            delete users[user_ids[1]];
                            users[user_ids[0]] = user;
                            users_table.find(`[data-user-id="${user_ids[1]}"]`).remove();
                            loadingGlobal(false);
                        });
                        loadingGlobal();
                    });
                    break;
            }
        });

        // Direct message
        $(admin).on('click', '.sb-send-direct-message', function () {
            let type = $(this).attr('data-type') ? $(this).attr('data-type') : direct_message_box.attr('data-type');
            let whatsapp = type == 'whatsapp';
            let box = whatsapp ? admin.find('#sb-whatsapp-send-template-box') : direct_message_box;
            let subject = box.find('.sb-direct-message-subject input').val();
            let message = whatsapp ? '' : box.find('textarea').val();
            let user_ids = box.find('.sb-direct-message-users').val().replace(/ /g, '');
            let template_name = false;
            let template_languages = false;
            let parameters = [];
            let phone_number_id = false;
            if (whatsapp) {
                let select = box.find('#sb-whatsapp-send-template-list');
                template_name = select.val();
                template_languages = select.find('option:selected').attr('data-languages');
                phone_number_id = select.find('option:selected').attr('data-phone-id');
                parameters = ['header', 'body', 'button'].map(id => box.find(`#sb-whatsapp-send-template-${id}`).val());
            }
            if (SBForm.errors(box)) {
                SBForm.showErrorMessage(box, 'Please complete the mandatory fields.');
            } else {
                if (loading(this)) {
                    return;
                }
                let user_details = [];
                if (message.includes('recipient_name') || parameters.join('').includes('recipient_name')) {
                    user_details.push('first_name', 'last_name');
                }
                if (message.includes('recipient_email') || parameters.join('').includes('recipient_email')) {
                    user_details.push('email');
                }
                if (type == 'message') {
                    SBF.ajax({
                        function: 'direct-message',
                        user_ids: user_ids,
                        message: message
                    }, (response) => {
                        $(this).sbLoading(false);
                        let send_email = SB_ADMIN_SETTINGS.notify_user_email;
                        let send_sms = SB_ADMIN_SETTINGS.sms_active_users;
                        if (SBF.errorValidation(response)) {
                            return SBForm.showErrorMessage(box, 'An error has occurred. Please make sure all user ids are correct.');
                        }
                        if (send_email || send_sms) {
                            SBF.ajax({
                                function: 'get-users-with-details',
                                user_ids: user_ids,
                                details: user_details.concat(send_email && send_sms ? ['email', 'phone'] : [send_email ? 'email' : 'phone'])
                            }, (response) => {
                                if (send_email && response.email.length) {
                                    recursiveSending(response, 'email', message, 0, send_sms ? response.phone : [], 'email', subject);
                                } else if (send_sms && response.phone.length) {
                                    recursiveSending(response, 'phone', message, 0, [], 'sms');
                                } else {
                                    admin.sbHideLightbox();
                                }
                            });
                        }
                        infoBottom(`${SBF.slugToString(type)} sent to all users.`);
                    });
                } else {
                    let slug = type == 'custom_email' ? 'email' : 'phone';
                    SBF.ajax({
                        function: 'get-users-with-details',
                        user_ids: user_ids,
                        details: user_details.concat([slug])
                    }, (response) => {
                        if (response[slug].length) {
                            recursiveSending(response, slug, message, 0, [], type, subject, template_name, parameters, template_languages, phone_number_id);
                        } else {
                            $(this).sbLoading(false);
                            return SBForm.showErrorMessage(box, 'No users found.');
                        }
                    });
                }
            }
        });

        function recursiveSending(user_ids, slug, message, i = 0, user_ids_sms = [], type, subject = false, template_name = false, parameters = false, template_languages = false, phone_number_id = false) {
            let settings = { whatsapp: ['whatsapp-send-template', 'messages', ' a phone number.', 'direct-whatsapp'], email: ['create-email', 'emails', ' an email address.', false], custom_email: ['send-custom-email', 'emails', ' an email address.', 'direct-emails'], sms: ['send-sms', 'text messages', ' a phone number.', 'direct-sms'] }[type];
            SBF.ajax({
                function: settings[0],
                to: user_ids[slug][i].value,
                recipient_id: user_ids[slug][i].id,
                sender_name: SB_ACTIVE_AGENT['full_name'],
                sender_profile_image: SB_ACTIVE_AGENT['profile_image'],
                subject: subject,
                message: message,
                template_name: template_name,
                parameters: parameters,
                template_languages: template_languages,
                template: false,
                phone_id: phone_number_id,
                user_name: user_ids.first_name ? (user_ids.first_name[i].value + ' ' + user_ids.last_name[i].value).trim() : false,
                user_email: user_ids.email ? user_ids.email[i].value : false
            }, (response) => {
                let user_ids_length = user_ids[slug].length;
                let box = type == 'whatsapp' ? admin.find('#sb-whatsapp-send-template-box') : direct_message_box;
                box.find('.sb-bottom > div').html(`${sb_('Sending')} ${sb_(settings[1])}... ${i + 1} / ${user_ids_length}`);
                if (response) {
                    if (response !== true && (('status' in response && response.status == 400) || ('error' in response && ![131030, 131009].includes(response.error.code)))) {
                        SBForm.showErrorMessage(box, response.error ? response.error.message : `${response.message} Details at ${response.more_info}`);
                        console.error(response);
                        box.find('.sb-loading').sbLoading(false);
                        box.find('.sb-bottom > div').html('');
                        return;
                    }
                    if (i < user_ids_length - 1) {
                        return recursiveSending(user_ids, slug, message, i + 1, user_ids_sms, type, subject, template_name, parameters, template_languages, phone_number_id);
                    } else {
                        if (user_ids_sms.length) {
                            recursiveSending(user_ids_sms, slug, message, 0, [], 'sms', false);
                        } else {
                            admin.sbHideLightbox();
                            if (settings[3]) {
                                SBF.ajax({ function: 'reports-update', name: settings[3], value: message.substr(0, 18) + ' | ' + user_ids_length });
                            }
                        }
                        infoBottom(user_ids_length == 1 ? 'The message has been sent.' : sb_('The message was sent to all users who have' + settings[2]));
                    }
                } else {
                    console.warn(response);
                }
            });
        }

        // User filters
        $(users_area).on('click', '.sb-filter-btn > i', function () {
            $(this).parent().toggleClass('sb-active');
        });

        /*
        * ----------------------------------------------------------
        * Settings area
        * ----------------------------------------------------------
        */

        // Open settings area by URL
        if (SBF.getURL('setting')) {
            SBSettings.open(SBF.getURL('setting'), true);
        }

        // Settings history
        $(settings_area).on('click', ' > .sb-tab > .sb-nav [id]', function () {
            let id = $(this).attr('id').substr(4);
            if (SBF.getURL('setting') != id) {
                pushState('?setting=' + id);
            }
        });

        // Upload
        $(admin).on('click', '.sb-repeater-upload, [data-type="upload-image"] .image, [data-type="upload-file"] .sb-btn, #sb-chatbot-add-files, #sb-import-settings a, #sb-import-users a', function () {
            let extensions = '';
            upload_target = this;
            if ($(this).attr('id') == 'sb-chatbot-add-files') {
                extensions = '.pdf,.txt,.json,.csv';
                chatbot_files_table.find('.sb-pending').remove();
                SBApps.openAI.train.skip_files = [];
                upload_function = function () {
                    let files = upload_input.prop('files');
                    let code = '';
                    for (var i = 0; i < files.length; i++) {
                        let size = parseInt(files[i].size / 1000);
                        code += `<tr class="sb-pending" data-name="${files[i].name}"><td><input type="checkbox" /></td><td>${files[i].name}<label>${sb_('Pending')}</label></td><td>${size ? size : 1} KB</td><td><i class="sb-icon-delete"></i></td></tr>`;
                    }
                    chatbot_files_table.append(code).removeClass('sb-hide');
                };
            } else if ($(this).parent().parent().attr('id') == 'sb-import-settings') {
                extensions = '.json';
                upload_on_success = (response) => {
                    if (loading(this)) return;
                    SBF.ajax({
                        function: 'import-settings',
                        file_url: response
                    }, (response) => {
                        if (response) {
                            infoBottom('Settings saved. Reload to apply the changes.');
                        } else {
                            infoPanel(response);
                        }
                        $(this).sbLoading(false);
                    });
                    upload_on_success = false;
                }
            } else if ($(this).parent().parent().attr('id') == 'sb-import-users') {
                extensions = '.csv';
                upload_on_success = (response) => {
                    if (loading(this)) return;
                    SBF.ajax({
                        function: 'import-users',
                        file_url: response
                    }, (response) => {
                        if (response) {
                            infoBottom('Users imported successfully.');
                        } else {
                            infoPanel(response);
                        }
                        $(this).sbLoading(false);
                    });
                    upload_on_success = false;
                }
            } else if ($(this).hasClass('image')) {
                extensions = '.png,.jpg,.jpeg,.gif,.webp';
            } else if ($(this).hasClass('sb-repeater-upload')) {
                upload_on_success = (response) => {
                    let parent = $(this).parent();
                    if (parent.find('.repeater-item:last-child input').val()) {
                        SBSettings.repeater.add(this);
                    }
                    parent.find('.repeater-item:last-child input').val(response);
                }
            }
            upload_input.attr('accept', extensions).prop('value', '').click();
        });

        $(settings_area).on('click', '[data-type="upload-image"] .image > i', function (e) {
            SBF.ajax({ function: 'delete-file', path: $(this).parent().attr('data-value') });
            $(this).parent().removeAttr('data-value').css('background-image', '');
            e.preventDefault();
            return false;
        });

        // Repeater
        $(admin).on('click', '.sb-repeater-add', function () {
            SBSettings.repeater.add(this);
        });

        $(admin).on('click', '.repeater-item > i', function () {
            setTimeout(() => {
                SBSettings.repeater.delete(this);
            }, 100);
        });

        // Color picker
        SBSettings.initColorPicker();

        $(settings_area).find('[data-type="color"]').focusout(function () {
            let color = $(this).find('input').val();
            if (color == 'rgb(255, 255, 255)' && ['color-admin-1', 'color-1'].includes($(this).attr('id'))) {
                color = '';
            }
            setTimeout(() => {
                $(this).find('input').val(color);
                $(this).find('.color-preview').css('background-color', color);
            }, 300);
            SBSettings.set($(this).attr('id'), [color, 'color']);
        });

        $(settings_area).on('click', '.sb-type-color .input i', function (e) {
            $(this).parent().find('input').removeAttr('style').val('');
        });

        // Color palette
        $(settings_area).on('click', '.sb-color-palette span', function () {
            let active = $(this).sbActive();
            $(this).closest('.sb-repeater').find('.sb-active').sbActive(false);
            $(this).sbActive(!active);
        });

        $(settings_area).on('click', '.sb-color-palette ul li', function () {
            $(this).parent().parent().attr('data-value', $(this).data('value')).find('span').sbActive(false);
        });

        // Select images
        $(settings_area).on('click', '[data-type="select-images"] .input > div', function () {
            $(this).siblings().sbActive(false);
            $(this).sbActive(true);
        });

        // Select checkbox
        $(settings_area).on('click', '.sb-select-checkbox-input', function () {
            let value = $(this).attr('data-value');
            if (value) {
                value.replace(/ /g, '').split(',').forEach((id) => {
                    $(this).next().find('#' + id).prop('checked', true);
                });
            }
            $(this).toggleClass('sb-active');
        });

        $(settings_area).on('click', '.sb-select-checkbox input', function () {
            let checked_value_ids = '';
            let checked_value_names = '';
            $(this).parent().siblings().addBack().each(function () {
                if ($(this).find('input').prop('checked')) {
                    checked_value_ids += $(this).find('input').attr('id') + ', ';
                    checked_value_names += $(this).find('label').html() + ', ';
                }
            });
            $(this).closest('.sb-select-checkbox').prev().attr('data-value', checked_value_ids.substring(0, checked_value_ids.length - 2)).val(checked_value_names.substring(0, checked_value_names.length - 2));
        });

        // AJAX select
        $(settings_area).on('click', '[data-type="select-ajax"]', function () {
            let keys = ['posts', 'messenger-get-posts'];
            let id = $(this).data('id');
            let input = $(this);
            if (!id) {
                id = $(this).attr('id');
            }
            if (!id) {
                id = $(this).closest('[id]').attr('id');
            }
            if (id != 'messenger-dm-comment-post-id') {
                keys = ['departments', 'get-departments'];
            }
            if (!input.is('input')) {
                input = input.find('input');
            }
            if (input.next().hasClass('sb-custom-select')) {
                return input.next().remove();
            }
            if (custom_selects[keys[0]]) {
                input.after(custom_selects[keys[0]]);
            } else {
                input.after('<div class="sb-custom-select sb-loading"></div>');
                SBF.ajax({
                    function: keys[1]
                }, (response) => {
                    let code = '<span data-value=""></span>';
                    let options = [];
                    if (id != 'messenger-dm-comment-post-id') {
                        options = Object.entries(response).map(([key, value]) => [key, value.name]);
                    } else {
                        options = response.map(item => [item.id, item.message]);
                    }
                    options.forEach((option) => {
                        code += `<span data-value="${option[0]}">${option[1]}</span>`;
                    });
                    custom_selects[keys[0]] = '<div class="sb-custom-select">' + code + '</div>';
                    input.next().remove();
                    input.after(custom_selects[keys[0]]);
                    input.sbLoading(false);
                    if (!options.length && keys[0] == 'departments') {
                        infoBottom('No departments found. Create departments from Settings > Miscellaneous > Departments.', 'info');
                    }
                });
            }
        });

        $(settings_area).on('click', '.sb-custom-select:not(.sb-ignore) > span', function (e) {
            $(this).parent().prev().attr('data-value', $(this).attr('data-value')).val($(this).html());
            $(this).parent().remove();
            e.preventDefault();
            return false;
        });

        // AJAX select checkbox
        $(settings_area).on('click', '[data-id="email-piping-tags"], [data-id="messenger-page-tags"], [data-id="whatsapp-cloud-numbers-tags"], [data-id="telegram-numbers-tags"], [data-id="line-tags"], #zalo-tags > input', function () {
            let select = $(this).next();
            let function_names = { tags: 'get-tags' };
            let id = $(this).data('id');
            if (!id) {
                id = $(this).attr('id');
            }
            if (!id) {
                id = $(this).closest('[id]').attr('id');
            }
            if (id.includes('-tags')) {
                id = 'tags';
            }
            if (!select.html()) {
                if (loading(select)) return;
                SBF.ajax({
                    function: function_names[id]
                }, (response) => {
                    let code = '';
                    let options = [];
                    let checked_values = $(this).attr('data-value');
                    if (checked_values) {
                        checked_values = checked_values.replace(/ /g, '').split(',');
                    } else {
                        checked_values = [];
                    }
                    if (id == 'tags') {
                        options = response.map(item => [item['tag-name'], item['tag-name']]);
                    }
                    options.forEach((option) => {
                        code += `<div class="multi-input-checkbox"><input id="${option[0]}" type="checkbox"${checked_values.includes(option[0].replace(/ /g, '')) ? ' checked' : ''}><label>${option[0]}</label></div>`;
                    });
                    select.html(code);
                    select.sbLoading(false);
                    if (!options.length && id == 'tags') {
                        infoBottom('No tags found. Create tags from Settings > Admin > Tags.', 'info');
                    }
                });
            }
        });

        // Save
        $(settings_area).on('click', '.sb-save-changes', function () {
            SBSettings.save(this);
        });

        // Miscellaneous
        $(settings_area).on('change', '#saved-replies [data-id="reply-name"], [data-id="rich-message-name"]', function () {
            $(this).val($(this).val().replace(/\s+/g, '-').replace(/-+/g, '-').replace(/^-+/, '').replace(/-+$/, '').replace(/ /g, ''));
        });

        $(settings_area).on('change', '#user-additional-fields [data-id="extra-field-name"]', function () {
            $(this).parent().next().find('input').val(SBF.stringToSlug($(this).val()));
        });

        $(settings_area).on('click', '#dialogflow-sync-btn a', function (e) {
            let url = 'https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com/auth/dialogflow%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-translation%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-language' + (settings_area.find('#google-calendar-active input').is(':checked') ? '%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar' : '') + '&response_type=code&access_type=offline&redirect_uri=' + SB_URL + '/apps/dialogflow/functions.php&client_id={client_id}&prompt=consent';
            if (SB_ADMIN_SETTINGS.cloud && settings_area.find('#google-sync-mode select').val() == 'auto') {
                if (SB_ADMIN_SETTINGS.credits) {
                    window.open(url.replace('{client_id}', SB_ADMIN_SETTINGS.google_client_id));
                    e.preventDefault();
                    return false;
                }
            } else {
                let client_id = settings_area.find('#google-client-id input').val();
                if (client_id && settings_area.find('#google-client-secret input').val()) {
                    window.open(url.replace('{client_id}', client_id));
                } else {
                    infoPanel('Before continuing enter Client ID and Client secret. Check the docs for more details.');
                }
                e.preventDefault();
                return false;
            }
        });

        $(settings_area).on('click', '#dialogflow-redirect-url-btn a', function (e) {
            infoPanel(`<pre>${SB_URL}/apps/dialogflow/functions.php</pre>`);
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#dialogflow-saved-replies a', function (e) {
            infoPanel('', 'alert', () => {
                if (!loading(this)) {
                    SBF.ajax({ function: 'dialogflow-saved-replies' }, () => {
                        $(this).sbLoading(false);
                    });
                }
            });
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#test-email-user a, #test-email-agent a', function () {
            let email = $(this).parent().find('input').val();
            if (email && email.indexOf('@') > 0 && !loading(this)) {
                SBF.ajax({
                    function: 'send-test-email',
                    to: email,
                    email_type: $(this).parent().parent().attr('id') == 'test-email-user' ? 'user' : 'agent'
                }, (response) => {
                    infoPanel(response === true ? 'The message has been sent.' : response, 'info');
                    $(this).sbLoading(false);
                });
            }
        });

        $(settings_area).on('click', '#email-server-troubleshoot a', function (e) {
            settings_area.find('#test-email-user input').val(SB_ACTIVE_AGENT.email).next().click()[0].scrollIntoView({ behavior: 'smooth' });
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#test-sms-user a, #test-sms-agent a', function () {
            let phone_number = $(this).parent().find('input').val();
            if (phone_number && !loading(this)) {
                SBF.ajax({
                    function: 'send-sms',
                    message: 'Hello World!',
                    to: phone_number
                }, (response) => {
                    infoPanel(response && ['sent', 'queued'].includes(response.status) ? 'The message has been sent.' : `<pre>${JSON.stringify(response)}</pre>`);
                    $(this).sbLoading(false);
                });
            }
        });

        $(settings_area).on('click', '.sb-timetable > div > div > div', function () {
            let timetable = $(this).closest('.sb-timetable');
            let active = $(this).sbActive();
            $(timetable).find('.sb-active').sbActive(false);
            if (active) {
                $(this).sbActive(false).find('.sb-custom-select').remove();
            } else {
                let select = timetable.find('> .sb-custom-select').html();
                timetable.find(' > div .sb-custom-select').remove();
                $(this).append(`<div class="sb-custom-select sb-ignore">${select}</div>`).sbActive(true);
            }
        });

        $(settings_area).on('click', '.sb-timetable .sb-custom-select span', function () {
            $(this).closest('.sb-timetable').find('> div > div > .sb-active').html($(this).html()).attr('data-value', $(this).attr('data-value'));
            $(this).parent().sbActive(false);
        });

        $(settings_area).on('click', '#system-requirements a', function (e) {
            let code = '';
            SBF.ajax({
                function: 'system-requirements'
            }, (response) => {
                for (var key in response) {
                    code += `<div class="sb-input"><span>${sb_(SBF.slugToString(key))}</span><div${response[key] ? ' class="sb-green"' : ''}>${response[key] ? sb_('Success') : sb_('Error')}</div></div>`;
                }
                loadingGlobal(false);
                SBAdmin.genericPanel('requirements', 'System requirements', code);
            });
            loadingGlobal();
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#sb-path a', function (e) {
            SBF.ajax({
                function: 'path'
            }, (response) => {
                infoPanel(`<pre>${response}</pre>`);
            });
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#sb-url a', function (e) {
            infoPanel(`<pre>${SB_URL}</pre>`);
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#delete-leads a', function (e) {
            if (!$(this).sbLoading()) {
                infoPanel('All leads, including all the linked conversations and messages, will be deleted permanently.', 'alert', () => {
                    $(this).sbLoading(true);
                    SBF.ajax({
                        function: 'delete-leads'
                    }, () => {
                        infoPanel('Leads and conversations successfully deleted.');
                        $(this).sbLoading(false);
                    });
                });
            }
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#sb-export-settings a', function (e) {
            e.preventDefault();
            if (loading(this)) return;
            SBF.ajax({
                function: 'export-settings'
            }, (response) => {
                dialogDeleteFile(response, 'sb-export-settings-close', 'Settings exported');
                $(this).sbLoading(false);
            });
            return false;
        });

        $(admin).on('click', '#sb-export-settings-close .sb-close, #sb-export-users-close .sb-close, #sb-export-report-close .sb-close', function () {
            SBF.ajax({ function: 'delete-file', path: admin.find('.sb-dialog-box p pre').html() });
        });

        if (!SB_ADMIN_SETTINGS.cloud) {
            $(settings_area).on('click', '#push-notifications-sw-path a', function (e) {
                let path = urlStrip(location.href.replace(location.host, '')).replace('admin.php', '');
                if (path.includes('?')) {
                    path = path.substring(0, path.indexOf('?'));
                }
                infoPanel('<pre>' + path + '</pre>');
                e.preventDefault();
                return false;
            });
        }

        $(settings_area).on('click', '#push-notifications-btn a', function (e) {
            if (SB_ADMIN_SETTINGS.cloud || settings_area.find('#push-notifications-provider select').val() == 'onesignal') {
                if (typeof OneSignal != ND) {
                    OneSignal.Slidedown.promptPush({ force: true });
                } else {
                    SBF.serviceWorker.initPushNotifications();
                }
            } else {
                Notification.requestPermission();
            }
            e.preventDefault();
            return false;
        });

        $(settings_area).on('input', '#sb-search-settings', function () {
            let search = $(this).val().toLowerCase();
            SBF.search(search, () => {
                let code = '';
                let dropdown = settings_area.find('.sb-search-dropdown-items');
                if (search.length > 2) {
                    let navs = settings_area.find('> .sb-tab > .sb-nav li').map(function () { return $(this).text().trim() }).get();
                    settings_area.find('.sb-setting').each(function () {
                        let keywords = $(this).attr('data-keywords');
                        let id = $(this).attr('id');
                        if ((keywords && keywords.includes(search)) || (id && id.replaceAll('-', '-').includes(search)) || $(this).find('.sb-setting-content').text().toLowerCase().includes(search)) {
                            let index = $(this).parent().index();
                            code += `<div data-tab-index="${index}" data-setting="${$(this).attr('id')}">${navs[index]} > ${$(this).find('h2').text()}</div>`;
                        }
                    });
                }
                dropdown.html(code);
                if (dropdown.outerHeight() > $(window).height() - 100) {
                    dropdown.css('max-height', $(window).height() - 100);
                    dropdown.addClass('sb-scroll-area');
                } else {
                    dropdown.removeClass('sb-scroll-area');
                }
            });
        });

        $(settings_area).on('click', '.sb-search-dropdown-items div', function () {
            let index = $(this).attr('data-tab-index');
            let item = settings_area.find('> .sb-tab > .sb-nav li').eq(index);
            item.click();
            item.get(0).scrollIntoView();
            settings_area.find('#' + $(this).attr('data-setting'))[0].scrollIntoView();
        });

        // Slack  
        if (!SB_ADMIN_SETTINGS.cloud || !SB_ADMIN_SETTINGS.slack_client_id) {
            $(settings_area).on('click', '#slack-button a', () => {
                window.open('https://board.support/synch/?service=slack&plugin_url=' + SB_URL + cloudURL());
                return false;
            });
        }

        $(settings_area).on('click', '#slack-test a', function (e) {
            if (loading(this)) return;
            SBF.ajax({
                function: 'send-slack-message',
                user_id: false,
                full_name: SB_ACTIVE_AGENT['full_name'],
                profile_image: SB_ACTIVE_AGENT['profile_image'],
                message: 'Lorem ipsum dolor sit amete consectetur adipiscing elite incidido labore et dolore magna aliqua.',
                attachments: [['Example link', SB_URL + '/media/user.svg'], ['Example link two', SB_URL + '/media/user.svg']],
                channel: settings_area.find('#slack-channel input').val()
            }, (response) => {
                if (SBF.errorValidation(response)) {
                    if (response[1] == 'slack-not-active') {
                        infoPanel('Please first activate Slack, then save the settings and reload the admin area.');
                    } else {
                        infoPanel('Error. Response: ' + JSON.stringify(response));
                    }
                } else {
                    infoPanel(response[0] == 'success' ? 'Slack message successfully sent. Check your Slack app!' : JSON.stringify(response));
                }
                $(this).sbLoading(false);
            });
            e.preventDefault();
            return false;
        });

        $(settings_area).on('click', '#tab-slack', function () {
            let input = settings_area.find('#slack-agents .input');
            input.html('<div class="sb-loading"></div>');
            SBF.ajax({
                function: 'slack-users'
            }, (response) => {
                let code = '';
                if (SBF.errorValidation(response, 'slack-token-not-found')) {
                    code = `<p>${sb_('Synchronize Slack and save changes before linking agents.')}</p>`;
                } else {
                    let select = '<option value="-1"></option>';
                    response.agents.forEach(agent => {
                        select += `<option value="${agent.id}">${agent.name}</option>`;
                    });
                    response.slack_users.forEach(user => {
                        let existing_value = input.find(`#${user.id} select`).val();
                        code += `<div id="${user.id}" data-type="select" class="multi-input-select"><label>${user.name}</label><select>${select.replace(`value="${existing_value}">`, `value="${existing_value}" selected>`)}</select></div>`;
                    });
                }
                input.html(code);
                SBSettings.set('slack-agents', [response.saved, 'multi-input']);
            });
        });

        $(settings_area).on('click', '#slack-archive-channels a', function (e) {
            e.preventDefault();
            if (loading(this)) return;
            SBF.ajax({
                function: 'archive-slack-channels'
            }, (response) => {
                if (response === true) {
                    infoPanel('Slack channels archived successfully!');
                }
                $(this).sbLoading(false);
            });
        });

        $(settings_area).on('click', '#slack-channel-ids a', function (e) {
            e.preventDefault();
            if (loading(this)) return;
            SBF.ajax({
                function: 'slack-channels',
                code: true
            }, (response) => {
                infoPanel(response, 'info', false, '', '', true);
                $(this).sbLoading(false);
            });
        });

        // Messenger, WhatsApp, Text messages, Twitter, Telegram, Viber, Zalo
        $(settings_area).on('click', '#whatsapp-twilio-btn a, #whatsapp-twilio-get-configuartion-btn a, #sms-btn a, #wechat-btn a, #twitter-callback a, #viber-webhook a, #zalo-webhook a, [data-id="line-webhook"], #messenger-path-btn a', function (e) {
            let id = $(this).closest('[id]').attr('id');
            let extra = '';
            e.preventDefault();
            if (id == 'line') {
                extra = $(this).closest('.repeater-item').find('[data-id="line-secret"]').val();
                if (!extra) {
                    return;
                } else {
                    extra = '?line_secret=' + extra;
                }
            }
            infoPanel(`<pre>${SB_URL + (id == 'sms-btn' ? '/include/api.php' : ('/apps/' + (id.includes('-') ? id.substring(0, id.indexOf('-')) : id) + '/post.php')) + extra + cloudURL().replace('&', extra ? '&' : '?')}</pre>`);
            return false;
        });

        $(settings_area).on('click', '[data-id="telegram-numbers-button"], #viber-button a, #whatsapp-360-button a', function (e) {
            let calls = { 'telegram-button': ['#telegram-token input', 'telegram-synchronization', ['result', true]], 'viber-button': ['#viber-token input', 'viber-synchronization', ['status_message', 'ok']], 'whatsapp-360-button': ['#whatsapp-360-key input', 'whatsapp-360-synchronization', ['success', true]] };
            let id = $(this).parent().attr('id');
            let token;
            let is_additional_number = false;
            if (!id) {
                let buttons = { 'telegram-numbers-button': 'telegram-button' };
                let inputs = { 'telegram-button': 'telegram-numbers-token' };
                id = buttons[$(this).attr('data-id')];
                token = $(this).closest('.repeater-item').find(`[data-id="${inputs[id]}"]`).val().trim();
                is_additional_number = true;
            } else {
                token = settings_area.find(calls[id][0]).val().trim();
            }
            calls = calls[id];
            e.preventDefault();
            if (!token || loading(this)) return false;
            SBF.ajax({
                function: calls[1],
                token: token,
                cloud_token: cloudURL(),
                is_additional_number: is_additional_number
            }, (response) => {
                infoPanel(calls[2][0] in response && response[calls[2][0]] == calls[2][1] ? 'Synchronization completed.' : JSON.stringify(response));
                $(this).sbLoading(false);
            });
            return false;
        });

        $(settings_area).on('click', '#whatsapp-test-template a', function (e) {
            e.preventDefault();
            let phone = $(this).parent().find('input').val();
            if (!phone || loading(this)) return;
            SBF.ajax({
                function: 'whatsapp-send-template',
                to: phone
            }, (response) => {
                infoPanel(response ? ('error' in response ? (response.error.message ? response.error.message : response.error) : 'Message sent, check your WhatsApp!') : response);
                $(this).sbLoading(false);
            });
            return false;
        });

        $(settings_area).on('click', '#twitter-subscribe a', function (e) {
            e.preventDefault();
            if (loading(this)) return false;
            SBF.ajax({
                function: 'twitter-subscribe',
                cloud_token: cloudURL()
            }, (response) => {
                infoPanel(response === true ? 'Synchronization completed.' : JSON.stringify(response));
                $(this).sbLoading(false);
            });
            return false;
        });

        if (!SB_ADMIN_SETTINGS.cloud) {
            $(settings_area).on('click', '#messenger-sync-btn a', () => {
                window.open('https://board.support/synch/?service=messenger&plugin_url=' + SB_URL + cloudURL());
                return false;
            });
        }

        $(settings_area).on('click', '#messenger-unsubscribe a', function (e) {
            e.preventDefault();
            infoPanel('', 'alert', () => {
                if (loading(this)) return false;
                SBF.ajax({
                    function: 'messenger-unsubscribe'
                }, (response) => {
                    $(this).sbLoading(false);
                    if (response) {
                        infoPanel(JSON.stringify(response));
                    } else {
                        settings_area.find('#messenger-pages .repeater-item > i').click();
                        setTimeout(() => {
                            SBSettings.save();
                            infoPanel('Operation successful.');
                        }, 300);
                    }
                });
            });
            return false;
        });

        // Settings visibility
        $(settings_area).on('change', '.sb-type-select select,.multi-input-select select', function () {
            let value = $(this).val();
            switch ($(this).closest('[id]').attr('id')) {
                case 'open-ai-mode':
                    SBSettings.visibility(2, value != 'assistant');
                    break;
                case 'messenger-sync-mode':
                    SBSettings.visibility(1, value != 'manual');
                    break;
                case 'push-notifications-provider':
                    SBSettings.visibility(0, value == 'pusher');
                    SBF.ajax({ function: 'update-sw', url: value == 'pusher' ? 'https://js.pusher.com/beams/service-worker.js' : 'https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js' });
                    break;
                case 'header-type':
                    SBSettings.visibility(3, value == 'agents');
                    break;

            }
        });

        // WordPress
        $(settings_area).on('click', '#wp-sync a', function (e) {
            e.preventDefault();
            if (loading(this)) return false;
            SBApps.wordpress.ajax('wp-sync', {}, (response) => {
                if (response === true || response === '1') {
                    SBUsers.update();
                    infoPanel('WordPress users successfully imported.');
                } else {
                    infoPanel('Error. Response: ' + JSON.stringify(response));
                }
                $(this).sbLoading(false);
            });
            return false;
        });

        $('body').on('click', '#wp-admin-bar-logout', function () {
            SBF.logout(false);
        });

        $(settings_area).on('click', '#whatsapp-clear-flows a', function (e) {
            e.preventDefault();
            SBF.ajax({
                function: 'whatsapp-clear-flows'
            });
        });

        // Translations
        $(settings_area).on('click', '#tab-translations', function () {
            let nav = settings_area.find('.sb-translations > .sb-nav > ul');
            if (!nav.html()) {
                let code = '';
                for (var key in SB_LANGUAGE_CODES) {
                    if (key == 'en') continue;
                    code += `<li data-code="${key}"><img src="${SB_URL}/media/flags/${key}.png" />${SB_LANGUAGE_CODES[key]}</li>`;
                }
                nav.html(code);
            }
        });

        $(settings_area).on('click', '.sb-translations .sb-nav li', function () {
            SBSettings.translations.load($(this).data('code'));
        });

        $(settings_area).on('click', '.sb-translations .sb-menu-wide li', function () {
            settings_area.find(`.sb-translations [data-area="${$(this).data('value')}"]`).sbActive(true).siblings().sbActive(false);
        });

        $(settings_area).on('click', '.sb-add-translation', function () {
            settings_area.find('.sb-translations-list > .sb-active').prepend(`<div class="sb-setting sb-type-text sb-new-translation"><input type="text" placeholder="${sb_('Enter original text...')}"><input type="text" placeholder="${sb_('Enter translation...')}"></div></div>`);
        });

        $(settings_area).on('input', '.sb-search-translation input', function () {
            let search = $(this).val().toLowerCase();
            SBF.search(search, () => {
                if (search.length > 1) {
                    settings_area.find('.sb-translations .sb-content > .sb-active label').each(function () {
                        let value = $(this).html().toLowerCase();
                        if (value.includes(search) && value != temp) {
                            let scroll_area = settings_area.find('.sb-scroll-area');
                            scroll_area[0].scrollTop = 0;
                            scroll_area[0].scrollTop = $(this).position().top - 80;
                            temp = value;
                            return false;
                        }
                    });
                }
            });
        });

        // Email piping manual sync
        $(settings_area).on('click', '[data-id="email-piping-sync"]', function (e) {
            if (loading(this)) return;
            SBF.ajax({
                function: 'email-piping',
                force: true
            }, (response) => {
                infoPanel(response === true ? 'Syncronization completed.' : response);
                $(this).sbLoading(false);
            });
            e.preventDefault();
        });

        // Automations
        $(settings_area).on('click', '#tab-automations', function () {
            SBSettings.automations.get(() => {
                SBSettings.automations.populate();
                loadingGlobal(false);
            }, true);
            loadingGlobal();
        });

        $(admin).on('click', '.sb-add-condition', function () {
            SBSettings.automations.addCondition($(this).prev());
        });

        $(admin).on('change', '.sb-condition-1 select', function () {
            SBSettings.automations.updateCondition(this);
        });

        $(admin).on('change', '.sb-condition-2 select', function () {
            $(this).parent().next().setClass('sb-hide', ['is-set', 'is-not-set'].includes($(this).val()));
        });

        $(automations_area_select).on('click', 'li', function () {
            SBSettings.automations.populate($(this).data('value'));
        });

        $(automations_area_nav).on('click', 'li', function () {
            SBSettings.automations.show($(this).attr('data-id'));
        });

        $(automations_area).on('click', '.sb-add-automation', function () {
            SBSettings.automations.add();
        });

        $(automations_area_nav).on('click', 'li i', function () {
            infoPanel(`The automation will be deleted permanently.`, 'alert', () => {
                SBSettings.automations.delete(this);
            });
        });

        // Conflicts alerts and warnings
        let warning_messages = ['Settings > {R} won\'t work if Settings > {R2} is active.'];
        $(settings_area).on('click', '.sb-setting', function (e) {
            let id = $(this).attr('id');
            if ($(this).hasClass('sb-type-multi-input')) {
                id = $(e.target).parent().attr('id');
            }
            switch (id) {
                case 'close-chat':
                case 'close-message':
                    if (settings_area.find('#close-active input').is(':checked') && settings_area.find('#close-chat input').is(':checked')) {
                        infoBottom(warning_messages[0].replace('{R}', 'Messages > Close message').replace('{R2}', 'Chat > Close chat'), 'info');
                    }
                    break;
                case 'chat-timetable':
                case 'follow-message':
                case 'queue':
                case 'routing':
                    if (((id == 'queue' && settings_area.find('#queue-active input').is(':checked')) || (id == 'routing' && settings_area.find('#routing input').is(':checked')) || (id == 'follow-message' && settings_area.find('#follow-active input').is(':checked')) || (id == 'chat-timetable' && settings_area.find('#chat-timetable-active input').is(':checked'))) && settings_area.find('#dialogflow-human-takeover-active input').is(':checked')) {
                        infoBottom('Since Settings > Artificial Intelligence > Human takeover is active, this option will only take effect during human takeover.', 'info');
                    }
                    break;
                case 'notify-agent-email':
                case 'push-notifications':
                case 'sms':
                    if (((id == 'sms' && settings_area.find('#sms-active-agents input').is(':checked')) || (id == 'push-notifications' && settings_area.find('#push-notifications-active input').is(':checked')) || (id == 'notify-agent-email' && settings_area.find('#notify-agent-email input').is(':checked'))) && settings_area.find('#dialogflow-human-takeover-active input').is(':checked')) {
                        infoBottom('Since Settings > Artificial Intelligence > Human takeover is active, notifications will be sent only after the human takeover.', 'info');
                    }
                    break;
                case 'privacy':
                    if (settings_area.find('#privacy-active input').is(':checked') && settings_area.find('#registration-required select').val()) {
                        infoBottom(warning_messages[0].replace('{R}', 'Messages > Privacy message').replace('{R2}', 'Users > Require registration'), 'info');
                    }
                    break;
                case 'google-multilingual-translation':
                    if ($(e.target).is(':checked') && settings_area.find('#open-ai-active input').is(':checked') && !settings_area.find('#open-ai-training-data-language select').val()) {
                        infoBottom('If your OpenAI training data isn\'t in English, set the default language under OpenAI > Training data language.', 'info');
                    }
                    break;
                case 'articles-auto-translation':
                    if ($(e.target).is(':checked') && !settings_area.find('#google-multilingual-translation input').is(':checked')) {
                        infoBottom('Enable Settings > Artificial Intelligence > Google > Multilingual via translation to use this feature.', 'info');
                    }
                    break;
                case 'open-ai-prompt':
                    infoBottom('Custom prompts may break the chatbot, configure them carefully.', 'info');
                    break;
                case 'open-ai-tokens':
                case 'open-ai-temperature':
                case 'open-ai-presence-penalty':
                case 'open-ai-frequency-penalty':
                case 'open-ai-logit-bias':
                case 'open-ai-custom-model':
                    infoBottom('This is an advanced setting, incorrect values may break the chatbot. If you\'re unsure, leave it empty.', 'info');
                    break;
                case 'open-ai-user-train-conversations':
                    if ($(e.target).is(':checked')) {
                        infoBottom('This method is not recommended. See the docs for details.', 'info');
                    }
                    break;
                case 'google-calendar-active':
                    infoBottom('Sync Google again from Settings > Artificial Intelligence > Google > Synchronization.', 'info');
                    break;
                case 'google-calendar-slot-time':
                    infoBottom('Set the available booking times under Settings > Miscellaneous > Scheduled Office Hours.', 'info');
                    break;
                case 'dialogflow-human-takeover-disable-offline':
                case 'welcome-disable-office-hours':
                case 'follow-disable-office-hours':
                    if ((id == 'follow-disable-office-hours' && settings_area.find('#follow-disable-office-hours input').is(':checked')) || (id == 'welcome-disable-office-hours' && settings_area.find('#welcome-disable-office-hours input').is(':checked')) || (id == 'dialogflow-human-takeover-disable-offline' && settings_area.find('#dialogflow-human-takeover-disable-offline input').is(':checked'))) {
                        infoBottom('Set office hours in Settings > Miscellaneous > Office Hours.', 'info');
                    }
                    break;
            }
        });

        $(users_table_menu).on('click', '[data-type="online"]', function () {
            if (!SB_ADMIN_SETTINGS.visitors_registration) {
                infoBottom('Settings > Users > Register all visitors must be enabled to see online users.', 'info');
            }
        });

        $(settings_area).on('click', '#dialogflow-active,#dialogflow-welcome,#dialogflow-departments', function (e) {// Depreceated
            infoBottom('Warning! We will stop supporting Dialogflow by the end of 2025. All its features will be available through OpenAI. Please use OpenAI instead of Dialogflow.', 'info');
        });

        $(settings_area).on('change', '#registration-required select', function () {
            let value = $(this).val();
            if (['registration-login'].includes(value) && !settings_area.find('[id="reg-email"] input').is(':checked')) {
                infoBottom('The email field is required to activate the login form.', 'info');
            }
            if (value && settings_area.find('#privacy-active input').is(':checked')) {
                infoBottom(warning_messages[0].replace('{R}', 'Messages > Privacy message').replace('{R2}', 'Users > Require registration'), 'info');
            }
        });

        /*
        * ----------------------------------------------------------
        * Chatbot area
        * ----------------------------------------------------------
        */

        $(chatbot_area).on('click', '#sb-flow-add', function () {
            SBAdmin.genericPanel('flow-add', 'Enter the flow name', '<div class="sb-setting"><input type="text"></div>', ['Add new flow']);
        });

        $(admin).on('click', '#sb-add-new-flow', function () {
            SBApps.openAI.flows.set(admin.find('.sb-flow-add-box input').val());
            admin.sbHideLightbox();
        });

        $(flows_area).on('click', '.sb-flow-block', function () {
            flows_area.find('.sb-flow-block,.sb-flow-add-block').sbActive(false);
            $(this).sbActive(true);
            let block = SBApps.openAI.flows.blocks.get();
            let code;
            let code_2 = '';
            let type = $(this).attr('data-type');
            let code_repeater = `<div class="sb-title">{R}</div><div data-type="repeater" class="sb-setting sb-type-repeater"><div class="input"><div class="sb-repeater">{R2}</div><div class="sb-btn sb-repeater-add sb-icon"><i class="sb-icon-plus"></i>${sb_('Add new item')}</div></div></div>`;
            let code_conditions = `<div class="sb-title">${sb_('Conditions')}</div><div class="sb-flow-conditions"></div><div class="sb-add-condition sb-btn sb-icon"><i class="sb-icon-plus"></i>${sb_('Add condition')}</div>`;
            let code_message = `<div class="sb-title">${sb_('Message')}</div><div class="sb-setting"><textarea placeholder="${sb_('The message sent to the user...')}">${block.message}</textarea></div>`;
            let code_select_user_details = SBApps.openAI.getCode.select_user_details();
            switch (type) {
                case 'start':
                    code_2 = SBSettings.getSelectDepartments(block.department);
                    if (code_2) {
                        code_2 = `<div class="sb-title">${sb_('Department')}</div><div class="sb-setting">${code_2}</div>`;
                    }
                    code_2 += `<div class="sb-title">${sb_('Source')}</div><div class="sb-setting">${SBApps.getSelectMessagingApps(block.conversation_source, true)}</div>`;
                    code = `<div class="sb-title">${sb_('Start event')}</div><div class="sb-setting"><select class="sb-flow-start-select"><option value="message"${block.start == 'message' ? ' selected' : ''}>${sb_('User message')}</option><option value="conversation"${block.start == 'conversation' ? ' selected' : ''}>${sb_('New conversation started')}</option><option value="load"${block.start == 'load' ? ' selected' : ''}>${sb_('On page load')}</option></select></div><div class="sb-title sb-title-flow-start${block.start == 'message' ? `` : ` sb-hide`}">${sb_('User message')}</div><div data-type="repeater" class="sb-setting sb-flow-start-messages sb-type-repeater"><div class="input"><div class="sb-repeater"><div class="repeater-item"><div class="sb-setting"><textarea data-id="message" placeholder="${sb_('Enter the message the user must send to start this flow')}"></textarea></div><i class="sb-icon-close"></i></div></div><div class="sb-btn sb-repeater-add sb-icon"><i class="sb-icon-plus"></i>${sb_('Add message')}</div></div></div>${code_conditions}${code_2}<div class="sb-title">${sb_('Disabled')}</div><div class="sb-setting"><input type="checkbox" id="sb-flow-disabled"${block.disabled ? ' checked' : ''}></div>`;
                    break;
                case 'choices':
                case 'button_list': // Depreceated
                    if (!block.options || !block.options.length) {
                        block.options = [''];
                    }
                    for (var i = 0; i < block.options.length; i++) {
                        code_2 += `<div class="repeater-item"><div><input data-id type="text" value="${block.options[i].replaceAll('\\,', ', ').replaceAll('  ', ' ')}"></div><i class="sb-icon-close"></i></div>`;
                    }
                    code = code_message + code_repeater.replace(`{R}`, sb_('Choices')).replace(`{R2}`, code_2) + `<div class="sb-title">${sb_('Conversational mode')}</div><div class="sb-setting"><input type="checkbox" id="sb-conversational-mode"${block.conversational_mode ? ' checked' : ''}></div>`;
                    break;
                case 'message':
                    if (!block.attachments || !block.attachments.length) {
                        block.attachments = [''];
                    }
                    for (var i = 0; i < block.attachments.length; i++) {
                        code_2 += `<div class="repeater-item"><div><input data-id type="text" value="${block.attachments[i]}" placeholder="${sb_('Enter a link...')}"></div><i class="sb-icon-close"></i></div>`;
                    }
                    code = code_message + code_repeater.replace(`{R}`, sb_('Attachments')).replace(`{R2}`, code_2).replace(`</div></div></div>`, `</div><i class="sb-repeater-upload sb-btn-icon sb-icon-clip"></i></div></div>`);
                    break;
                case 'video':
                    code = `${code_message}<div class="sb-title">${sb_('Video URL')}</div><div class="sb-setting"><input type="url" placeholder="${sb_('Enter a YouTube or Vimeo link...')}" value="${block.url}"></div>`;
                    break;
                case 'get_user_details':
                    if (!block.details || !block.details.length) {
                        block.details = [['', '', false]];
                    }
                    for (var i = 0; i < block.details.length; i++) {
                        code_2 += `<div class="repeater-item"><div>${code_select_user_details.replace(`"${block.details[i][0]}"`, `"${block.details[i][0]}" selected`)}<div class="sb-setting"><input type="text" placeholder="${sb_('Enter a description...')}" value="${block.details[i][1]}" /></div><div class="sb-setting"><label>${sb_('Required')}</label><input type="checkbox" ${block.details[i][2] ? ' checked' : ''}></div></div><i class="sb-icon-close"></i></div>`;
                    }
                    code = code_message + code_repeater.replace(`{R}`, sb_('User details')).replace(`{R2}`, code_2).replace('sb-type-repeater', 'sb-type-repeater sb-repeater-block-user-details');
                    break;
                case 'set_data':
                    code = SBApps.openAI.getCode.set_data(block.data);
                    break;
                case 'action':
                    code = SBApps.openAI.getCode.actions(block.actions);
                    break;
                case 'rest_api':
                    let keys = ['headers', 'save_response'];
                    code = `<div class="sb-title">${sb_('URL')}</div><div class="sb-setting"><input type="url" class="sb-rest-api-url" value="${block.url}"></div><div class="sb-title">${sb_('Method')}</div><div class="sb-setting"><select class="sb-rest-api-method"><option value="GET"${block.method == 'GET' ? ' selected' : ''}>GET</option><option value="POST"${block.method == 'POST' ? ' selected' : ''}>POST</option><option value="PUT"${block.method == 'PUT' ? ' selected' : ''}>PUT</option><option value="PATH"${block.method == 'PATH' ? ' selected' : ''}>PATH</option><option value="DELETE"${block.method == 'DELETE' ? ' selected' : ''}>DELETE</option></select></div><div class="sb-title">${sb_('Body')}</div><div class="sb-setting"><textarea placeholder="JSON">${block.body}</textarea></div>`;
                    for (var i = 0; i < keys.length; i++) {
                        let values = block[keys[i]];
                        if (!values || !values.length) {
                            values = [['', '']];
                        }
                        code += `<div class="sb-title">${sb_(SBF.slugToString(keys[i]))}</div><div data-type="repeater" class="sb-setting sb-type-repeater sb-repeater-block-rest-api sb-rest-api-${keys[i]}"><div class="input"><div class="sb-repeater">`;
                        for (var j = 0; j < values.length; j++) {
                            code += `<div class="repeater-item"><div>${i == 1 ? code_select_user_details.replace(`"${values[j][0]}"`, `"${values[j][0]}" selected`) : `<div class="sb-setting"><input type="text" placeholder="${sb_('Key')}" value="${values[j][0]}" /></div>`}<div class="sb-setting"><input type="text" placeholder="${sb_(i == 1 ? 'e.g. data.id' : 'Value')}" value="${values[j][1]}" /></div></div><i class="sb-icon-close"></i></div>`;
                        }
                        code += `</div><div class="sb-btn sb-repeater-add sb-icon"><i class="sb-icon-plus"></i>${sb_('Add new item')}</div></div></div>`;
                    }
                    break;
                case 'condition':
                    code = code_conditions;
                    break;
                case 'tools':
                    let headers = block.headers;
                    let properties = block.properties;
                    code = code_message + `<div class="sb-title">${sb_('URL')}</div><div class="sb-setting"><input type="url" class="sb-tools-url" value="${block.url}"></div><div class="sb-title">${sb_('Method')}</div><div class="sb-setting"><select class="sb-tools-method"><option value="GET"${block.method == 'GET' ? ' selected' : ''}>GET</option><option value="POST"${block.method == 'POST' ? ' selected' : ''}>POST</option><option value="PUT"${block.method == 'PUT' ? ' selected' : ''}>PUT</option><option value="PATH"${block.method == 'PATH' ? ' selected' : ''}>PATH</option><option value="DELETE"${block.method == 'DELETE' ? ' selected' : ''}>DELETE</option></select></div>`;
                    if (!headers || !headers.length) {
                        headers = [['', '']];
                    }
                    if (!properties || !properties.length) {
                        properties = [['', '', '']];
                    }
                    for (var i = 0; i < headers.length; i++) {
                        code_2 += `<div class="repeater-item"><div><input type="text" placeholder="${sb_('Key')}" value="${headers[i][0]}" /><input type="text" placeholder="${sb_('Value')}" value="${headers[i][1]}" /></div><i class="sb-icon-close"></i></div>`;
                    }
                    code += code_repeater.replace(`{R}`, sb_('Headers')).replace(`{R2}`, code_2).replace('sb-type-repeater', 'sb-type-repeater sb-setting sb-repeater-inputs-h sb-repeater-block-tools-headers');
                    code_2 = '';
                    for (var i = 0; i < properties.length; i++) {
                        code_2 += `<div class="repeater-item"><div><input type="text" placeholder="${sb_('Name')}" value="${properties[i][0]}" /></div><div><input type="text" placeholder="${sb_('Description')}" value="${properties[i][1]}" /></div><div><input type="text" placeholder="${sb_('Allowed values separated by commas')}" value="${properties[i][2]}" /></div><i class="sb-icon-close"></i></div>`;
                    }
                    code += code_repeater.replace(`{R}`, sb_('Properties')).replace(`{R2}`, code_2).replace('sb-type-repeater', 'sb-type-repeater sb-setting sb-repeater-inputs-v sb-repeater-block-tools-properties');
                    break;
                case 'flow_connector':
                    code = `<div class="sb-title">${sb_('Flow')}</div><div class="sb-setting"><select class="sb-flows-select">`;
                    let flows = SBApps.openAI.flows.flows;
                    for (var i = 0; i < flows.length; i++) {
                        if (flows[i].name != SBApps.openAI.flows.getActiveName()) {
                            code += `<option value="${flows[i].name}" ${flows[i].name == block.flow_name ? ' selected' : ''}>${flows[i].name}</option>`;
                        }
                    }
                    code += '</select></div>';
                    break;
            }
            if (type != 'start') {
                code += `<div id="sb-block-delete" class="sb-btn-text"><i class="sb-icon-delete"></i>${sb_('Delete')}</div>`;
            }
            SBAdmin.genericPanel('flow-block', SBF.slugToString(type), code, ['Save changes'], '', true);
            if (type == 'start' || type == 'condition') {
                let repeater = admin.find('.sb-flow-start-messages .sb-repeater');
                let code = SBSettings.repeater.set(block.message, repeater.find('.repeater-item:last-child'));
                SBSettings.automations.setConditions(block.conditions, admin.find('.sb-flow-conditions'));
                if (code) {
                    repeater.html(code);
                }
            }
            step_scroll_positions = [];
            flows_area.find('> div').each(function () {
                step_scroll_positions.push($(this).find('> div')[0].scrollTop);
            });
        });

        $(admin).on('click', '.sb-flow-block-box #sb-save-changes', function () {
            let block = SBApps.openAI.flows.blocks.get();
            let box = admin.find('.sb-flow-block-box');
            block.message = box.find('textarea').val();
            switch (block.type) {
                case 'start':
                    block.start = box.find('select').val();
                    block.message = block.start == 'message' ? SBSettings.repeater.get(box.find('.sb-flow-start-messages .repeater-item')) : '';
                    block.disabled = box.find('#sb-flow-disabled').is(':checked');
                    block.department = box.find('.sb-select-departments').val();
                    block.conversation_source = box.find('.sb-select-messaging-apps').val();
                    block.conditions = SBSettings.automations.getConditions(box.find('.sb-flow-conditions'));
                    if (block.message.length && block.message[0].message.trim().split(' ').length < 3) {
                        return box.find('.sb-info').sbActive(true).html(sb_('The message must contain at least 3 words.'));
                    }
                    break;
                case 'choices':
                case 'button_list': // Depreceated
                    block.options = box.find('.sb-repeater input').map(function () { return $(this).val().trim().replaceAll(',', '\\,') }).get().filter(function (value) { return value != '' });
                    block.conversational_mode = box.find('#sb-conversational-mode').is(':checked');
                    break;
                case 'message':
                    block.attachments = box.find('.sb-repeater input').map(function () { return $(this).val().trim() }).get().filter(function (value) { return value != '' });
                    break;
                case 'video':
                    block.url = box.find('input').val();
                    break;
                case 'get_user_details':
                    block.details = box.find('.repeater-item').map(function () { return [[$(this).find('select').val(), $(this).find('input[type=text]').val(), $(this).find('input[type=checkbox]').is(':checked')]] }).get();
                    break;
                case 'action':
                case 'set_data':
                    block[block.type == 'action' ? 'actions' : 'data'] = box.find('.repeater-item').map(function () { return [[$(this).find('select').val(), $(this).find('input').length ? $(this).find('input').val().replace(/https?:\/\/|["|:]/g, '') : '']] }).get();
                    break;
                case 'rest_api':
                    block.headers = box.find('.sb-rest-api-headers .repeater-item').map(function () { return [[$(this).find('input').eq(0).val(), $(this).find('input').eq(1).val()]] }).get();
                    block.save_response = box.find('.sb-rest-api-save_response .repeater-item').map(function () { return [[$(this).find('select').val(), $(this).find('input').val()]] }).get();
                    block.url = box.find('.sb-rest-api-url').val();
                    block.method = box.find('.sb-rest-api-method').val();
                    block.body = box.find('textarea').val();
                    delete block.message;
                    break;
                case 'condition':
                    block.conditions = SBSettings.automations.getConditions(box.find('.sb-flow-conditions'));
                    break;
                case 'tools':
                    block.url = box.find('.sb-tools-url').val();
                    block.method = box.find('.sb-tools-method').val();
                    block.headers = box.find('.sb-repeater-block-tools-headers .repeater-item').map(function () { return [[$(this).find('input').eq(0).val(), $(this).find('input').eq(1).val()]] }).get();
                    block.properties = box.find('.sb-repeater-block-tools-properties .repeater-item').map(function () { return [[$(this).find('input').eq(0).val(), $(this).find('input').eq(1).val(), $(this).find('input').eq(2).val()]] }).get();
                    if (block.properties.length == 1 && !block.properties[0][0]) {
                        block.properties = [];
                    }
                    if (block.headers.length == 1 && !block.headers[0][0]) {
                        block.headers = [];
                    }
                    break;
                case 'flow_connector':
                    block.flow_name = box.find('.sb-flows-select').val();
                    break;
            }
            SBApps.openAI.flows.blocks.set(block);
            flows_area.find('> div').each(function () {
                $(this).find('> div')[0].scrollTop = step_scroll_positions[$(this).index()];
            });
            admin.sbHideLightbox();
        });

        $(admin).on('change', '.sb-repeater-block-actions select', function () {
            $(this).parent().next().remove();
            $(this).parent().parent().append(SBApps.openAI.getCode.action($(this).val(), ''));
        });

        $(admin).on('change', '.sb-flow-start-select', function () {
            admin.find('.sb-title-flow-start, .sb-flow-start-messages').setClass('sb-hide', $(this).val() != 'message');
        });

        $(flows_area).on('mouseleave', '.sb-flow-connectors > div, .sb-flow-block', function () {
            flows_area.find('.sb-flow-block-cnt').sbActive(false);
            is_over_connector = false;
            if ($(this).parent().hasClass('sb-flow-connectors')) {
                SBApps.openAI.flows.blocks.activateLinkedCnts($(this).closest('.sb-flow-block'));
            } else {
                flows_area.find('.sb-flow-connectors > div').sbActive(false);
            }
        });

        $(flows_area).on('mouseenter', '.sb-flow-connectors > div', function () {
            let block_cnt = $(this).closest('.sb-flow-block').parent();
            let next_block_cnt_indexes = SBApps.openAI.flows.blocks.getNextCntIndexes(SBApps.openAI.flows.getActiveIndex(), block_cnt.parent().parent().index(), block_cnt.index());
            is_over_connector = true;
            flows_area.find('> div').eq(block_cnt.parent().parent().index() + 1).find('.sb-flow-block-cnt').sbActive(false).eq(next_block_cnt_indexes[$(this).index()]).sbActive(true);
        });

        $(flows_area).on('mouseenter', '.sb-flow-block', function () {
            SBApps.openAI.flows.blocks.activateLinkedCnts(this);
        });

        $(flows_area).on('click', '.sb-flow-add-block', function () {
            flows_area.find('.sb-flow-block,.sb-flow-add-block').sbActive(false);
            $(this).sbActive(true);
            let active_blocks = SBApps.openAI.flows.steps.get()[SBApps.openAI.flows.blocks.getActiveCntIndex()].map(item => item.type);
            let all = !active_blocks.some(element => ['message', 'button_list', 'choices', 'video', 'get_user_details', 'condition'].includes(element)); // Depreceated: button_list
            let nav_items = [['set_data', 'Set data'], ['action', 'Action'], ['condition', 'Condition'], ['tools', 'Tools calling'], ['rest_api', 'REST API'], ['flow_connector', 'Flow connector']];
            let code = '';
            for (var i = 0; i < nav_items.length; i++) {
                if (!active_blocks.includes(nav_items[i][0]) && (nav_items[i][0] != 'condition' || !active_blocks.includes('choices'))) {
                    code += `<li data-value="${nav_items[i][0]}">${sb_(nav_items[i][1])}</li>`;
                }
            }
            SBAdmin.genericPanel('flows-blocks-nav', '', `<ul class="sb-menu">${all ? `<li>${sb_('Messages')} <ul><li data-value="message">${sb_('Send message')}</li><li data-value="choices">${sb_('Send choices')}</li><li data-value="video">${sb_('Send video')}</li></ul></li>` : ``}<li>${sb_('More')} <ul>${all ? `<li data-value="get_user_details">${sb_('Get user details')}</li>` : ``}${code}</ul></li></ul>`);
        });

        $(admin).on('click', '#sb-block-delete', function () {
            SBApps.openAI.flows.blocks.delete();
            admin.sbHideLightbox();
        });

        $(flows_nav).on('click', 'li', function () {
            SBApps.openAI.flows.show($(this).attr('data-value'));
        });

        $(flows_nav).on('click', 'li i', function (e) {
            infoPanel('The flow will be deleted.', 'alert', () => {
                SBApps.openAI.flows.delete($(this).parent().attr('data-value'));
            });
            e.preventDefault();
            return false;
        });

        $(admin).on('click', '.sb-flows-blocks-nav-box [data-value]', function () {
            SBApps.openAI.flows.blocks.add($(this).data('value'));
            admin.sbHideLightbox();
        });

        $(admin).on('mouseenter', '.sb-flow-scroll', function () {
            let is_back = $(this).hasClass('sb-icon-arrow-left');
            flow_scroll_interval = setInterval(() => {
                flows_area[0].scrollLeft += 10 * (is_back ? -1 : 1);
            }, 10);
        });

        $(admin).on('mouseleave', '.sb-flow-scroll', function () {
            clearInterval(flow_scroll_interval);
        });

        $(chatbot_area).on('click', '#sb-train-chatbot', function (e) {
            let success_text = 'The chatbot has been successfully trained.';
            let nav = chatbot_area.find('.sb-nav [data-value="conversations"]');
            infoPanel('<br><br><br><br><br>', 'info', false, 'sb-embeddings-box');
            e.preventDefault();
            if (SB_ADMIN_SETTINGS.cloud && SBCloud.creditsAlert(this, e)) {
                return false;
            }
            if (loading(this)) {
                return false;
            }
            if (chatbot_area.find('.sb-menu-chatbot .sb-active').attr('data-type') == 'flows') {
                SBApps.openAI.flows.save(() => {
                    infoPanel(success_text, 'info', false, false, 'icon-check');
                });
                $(this).sbLoading(false);
                return;
            }
            if (nav.sbActive()) {
                let to_update = [];
                for (var i = 0; i < conversations_qea.length; i++) {
                    let qea = chatbot_area.find(`#sb-chatbot-conversations [data-index="${i}"]`);
                    if (qea.length) {
                        qea = [qea.find('input').val(), qea.find('textarea').val()];
                        if (qea[0] != $('<textarea />').html(conversations_qea[i].question).text() || qea[1] != $('<textarea />').html(conversations_qea[i].answer).text()) {
                            conversations_qea[i].question = qea[0];
                            conversations_qea[i].answer = qea[1];
                            to_update.push(conversations_qea[i]);
                        }
                    } else {
                        conversations_qea[i].question = false;
                        conversations_qea[i].answer = false;
                        to_update.push(conversations_qea[i]);
                    }
                }
                if (to_update.length) {
                    SBF.ajax({
                        function: 'open-ai-save-conversation-embeddings',
                        qea: to_update
                    }, (response) => {
                        if (response[0] === true) {
                            infoPanel(success_text, 'info', false, false, 'icon-check');
                        } else if (!SBApps.openAI.train.isError(response[0])) {
                            infoPanel(response[0]);
                        }
                        nav.click();
                        $(this).sbLoading(false);
                    });
                } else {
                    $(this).sbLoading(false);
                    infoPanel(success_text, 'info', false, false, 'icon-check');
                }
                return;
            }
            SBApps.openAI.train.errors = [];

            // Files
            let index = 0;
            SBApps.openAI.train.files((response) => {

                // Website
                SBApps.openAI.train.urls = chatbot_area.find('[data-id="open-ai-sources-url"]').map(function () { return $(this).val().trim() }).get();
                SBApps.openAI.train.extract_url = chatbot_area.find('[data-id="open-ai-sources-extract-url"]').map(function () { return $(this).is(':checked') }).get();
                SBApps.openAI.train.website((response) => {

                    // Q&A
                    SBApps.openAI.train.qea((response) => {

                        // Articles
                        SBApps.openAI.train.articles((response) => {

                            // Finish
                            SBApps.openAI.init();
                            chatbot_area.find('#sb-repeater-chatbot-website .repeater-item i').click();

                            if (SBApps.openAI.train.errors.length) {
                                infoPanel(`<span>${sb_('The chatbot has been trained with errors. Check the console for more details.')}</span>\n\n<pre>${SBApps.openAI.train.errors.join('<br>').replaceAll('false,', '')}</pre>`, 'info', false, 'sb-errors-list-box', false, true);
                                console.error(SBApps.openAI.train.errors);
                            } else if (!SBApps.openAI.train.isError(response)) {
                                infoPanel(success_text, 'info', false, false, 'icon-check');
                            }
                            $(this).sbLoading(false);
                        });
                    });
                });
            });
            return false;
        });

        $(chatbot_area).on('click', '#sb-table-chatbot-files td i, #sb-table-chatbot-website td i, #sb-chatbot-delete-files, #sb-chatbot-delete-website, #sb-chatbot-delete-all-training, #sb-chatbot-delete-all-training-conversations', function () {
            let is_i = $(this).is('i');
            let tr = is_i ? $(this).closest('tr') : false;
            if (is_i && tr.hasClass('sb-pending')) {
                SBApps.openAI.train.skip_files.push(tr.attr('data-name'));
                tr.remove();
                if (!chatbot_files_table.find('tbody tr').length) {
                    chatbot_files_table.addClass('sb-hide');
                }
                return;
            }
            infoPanel('The training data will be permanently deleted.', 'alert', () => {
                let sources_to_delete = [];
                let id = $(this).attr('id');
                if (is_i) {
                    sources_to_delete = [tr.attr('data-url')];
                } else if (id == 'sb-chatbot-delete-all-training') {
                    sources_to_delete = 'all';
                } else if (id == 'sb-chatbot-delete-all-training-conversations') {
                    sources_to_delete = 'all-conversations';
                } else {
                    let table = $(id == 'sb-chatbot-delete-files' ? chatbot_files_table : chatbot_website_table);
                    if (!table.find('input:checked').length) {
                        table.find('tbody input').prop('checked', true);
                    }
                    table.find('tbody tr').each(function () {
                        if ($(this).find('input:checked').length) {
                            if ($(this).hasClass('sb-pending')) {
                                SBApps.openAI.train.skip_files.push($(this).attr('data-name'));
                                $(this).remove();
                            } else {
                                let url = $(this).attr('data-url');
                                sources_to_delete.push(url);
                                if (SBApps.openAI.train.sitemap_processed_urls.indexOf(url) > -1) {
                                    SBApps.openAI.train.sitemap_processed_urls[SBApps.openAI.train.sitemap_processed_urls.indexOf(url)] = false;
                                }
                            }
                        }
                    });
                }
                if (sources_to_delete.length) {
                    if (loading(this)) return;
                    SBF.ajax({
                        function: 'open-ai-embeddings-delete',
                        sources_to_delete: sources_to_delete
                    }, (response) => {
                        SBApps.openAI.init();
                        if (sources_to_delete == 'all') {
                            chatbot_area.find('.sb-nav [data-value="info"]').click();
                        } else if (sources_to_delete == 'all-conversations') {
                            chatbot_area.find('.sb-nav [data-value="conversations"]').click();
                        }
                        if (response === true) {
                            infoBottom('Training data deleted.');
                        } else {
                            infoPanel(response);
                        }
                        $(this).sbLoading(false);
                    });
                }
            });
            return false;
        });

        $(chatbot_area).on('click', '.sb-nav [data-value="conversations"]', function () {
            let area = chatbot_area.find('#sb-chatbot-conversations');
            if (loading(area)) return;
            SBF.ajax({
                function: 'open-ai-get-conversation-embeddings'
            }, (response) => {
                if (!response.length) {
                    area.html(`<p class="sb-no-results">${sb_('No conversations found.')}</p>`);
                } else {
                    let code = '';
                    conversations_qea = response;
                    for (var i = 0; i < response.length; i++) {
                        code += `<div class="repeater-item" data-value="${response[i].id}" data-index=${i}><div><label>${sb_('Question')}</label><input data-id="q" type="text" value="${response[i].question}" /></div><div class="sb-qea-repeater-answer"><label>${sb_('Answer')}</label><textarea data-id="a">${response[i].answer}</textarea></div><i class="sb-icon-close"></i></div>`;
                    }
                    area.find('.sb-repeater').html(code);
                }
                area.sbLoading(false);
            });
        });

        $(chatbot_area).on('click', '.sb-nav [data-value="info"]', function () {
            let area = chatbot_area.find('#sb-chatbot-info');
            if (loading(area)) return;
            SBF.ajax({
                function: 'open-ai-get-information'
            }, (response) => {
                let list = [['files', 'Files'], ['website', 'Website URLs'], ['qea', 'Q&A'], ['flows', 'Flows'], ['articles', 'Articles'], ['conversations', 'Conversations']];
                let code = `<h2>${sb_('Sources')}</h2><p>`;
                for (var i = 0; i < list.length; i++) {
                    code += response[list[i][0]] ? `${response[list[i][0]][1]} ${sb_(list[i][1])} (${response[list[i][0]][0]} ${sb_('chars')})<br>` : '';
                }
                code += `</p><h2>${sb_('Total detected characters')}</h2><p>${response.total} ${sb_('chars') + (response.limit ? ' / ' + response.limit + ' ' + sb_('limit') : '')}</p><hr><div id="sb-chatbot-delete-all-training" class="sb-btn">${sb_('Delete all training data')}</div>`;
                area.html(code);
                area.sbLoading(false);
            });
        });

        $(chatbot_area).on('click', '.sb-menu-chatbot [data-type]', function (e) {
            let type = $(this).data('type');
            switch (type) {
                case 'flows':
                case 'training':
                case 'playground':
                    let area = chatbot_area.find(`> [data-id="${type}"]`);
                    chatbot_area.find('> [data-id]').sbActive(false)
                    area.sbActive(true);
                    if (type == 'flows' && area.sbLoading()) {
                        SBF.ajax({ function: 'open-ai-flows-get' }, (response) => {
                            for (var i = 0; i < response.length; i++) {
                                if (response[i] && response[i].steps && response[i].name) {
                                    SBApps.openAI.flows.flows.push(response[i]);
                                }
                            }
                            let code = '';
                            for (var i = 0; i < response.length; i++) {
                                if (response[i]) {
                                    code += SBApps.openAI.flows.navCode(response[i].name, response[i].label);
                                }
                            }
                            flows_nav.html(code);
                            flows_nav.find('li:first-child').click();
                            area.sbLoading(false);
                        });
                    }
                    break;
                case 'settings':
                    SBSettings.open('dialogflow', true);
                    e.preventDefault;
                    return false;
            }
        });

        $(chatbot_website_table).on('click', '[data-url]', function (e) {
            if (e.target.nodeName != 'I' && e.target.nodeName != 'INPUT') {
                window.open($(this).attr('data-url'));
            }
        });

        $(chatbot_area).on('click', '#sb-table-chatbot-files th input, #sb-table-chatbot-website th input', function () {
            let is_checked = $(this).is(':checked');
            $(this).closest('table').find('tbody tr input').each(function () {
                $(this).prop('checked', is_checked);
            });
        });

        $(chatbot_qea_repeater).on('click', '.sb-enlarger-function-calling', function () {
            $(this).parent().parent().find('.sb-qea-repeater-answer').addClass('sb-hide');
        });

        $(chatbot_qea_repeater).on('change', '[data-id="open-ai-faq-set-data"] select', function () {
            $(this).parent().next().find('input').setClass('sb-hide', ['transcript', 'transcript_email', 'human_takeover', 'archive_conversation'].includes($(this).val()));
        });

        $(chatbot_qea_repeater).on('input click', '[data-id="open-ai-faq-answer"]', function () {
            $(this).prev().find('i').sbActive($(this).val().length > 2 && $(this).val().indexOf(' '));
        });

        $(chatbot_qea_repeater).on('click', '.sb-qea-repeater-answer > label > i', function () {
            let textarea = $(this).closest('.repeater-item').find('[data-id="open-ai-faq-answer"]');
            if (loading(this)) return;
            SBApps.openAI.rewrite(textarea.val(), (response) => {
                $(this).sbLoading(false);
                textarea.val(response);
            });
        });

        $(chatbot_playground_editor).on('click', '[data-value="send"]', function () {
            let textarea = chatbot_playground_editor.find('textarea');
            let message = textarea.val().trim();
            let is_auto_clear = chatbot_playground_editor.find('[data-value="auto-clear"]').is('.sb-active');
            textarea.val('');
            if (message && !loading(this)) {
                let code = `<div><div>${sb_('User')}</div><div><div><div class="sb-cnt"><div class="sb-message">${message}</div></div></div></div></div>`;
                let history = SBF.storage('playground-history');
                if (!history) {
                    history = [];
                }
                if (!history.includes(message)) {
                    history.unshift(message);
                }
                SBF.storage('playground-history', history);
                if (is_auto_clear) {
                    chatbot_playground_area.html(code);
                } else {
                    chatbot_playground_area.append(code);
                }
                chatbot_playground_area[0].scrollTop = chatbot_playground_area[0].scrollHeight;
                SBF.ajax({
                    function: 'open-ai-playground-message',
                    message: message,
                    clear: SBApps.openAI.playground.last_response === false || is_auto_clear
                }, (response) => {
                    if (response.conversation) {
                        let code = '';
                        for (var key in response.conversation.messages) {
                            let message = response.conversation.messages[key];
                            if (message.message) {
                                code += `<div data-type="${message.user_type}" data-message-id="${message.id}"><div>${sb_(SBF.isAgent(message.user_type) ? 'Assistant' : 'User')}<div><i class="sb-icon-close sb-btn-icon sb-btn-red"></i></div></div><div>${(new SBMessage(message)).getCode()}</div></div>`;
                            }
                        }
                        chatbot_playground_area.html(code);
                        chatbot_playground_area[0].scrollTop = chatbot_playground_area[0].scrollHeight;
                        if (response.playground) {
                            let code = '';
                            for (var key in response.playground.usage) {
                                if (['string', 'number'].includes(typeof response.playground.usage[key])) {
                                    code += `<b>${SBF.slugToString(key)}</b>: ${response.playground.usage[key]}<br>`;
                                }
                            }
                            SBApps.openAI.playground.last_response = response.playground;
                            chatbot_area.find('.sb-playground-info').html(code + `<div id="sb-playground-query" class="sb-btn-text">${sb_('View code')}</div>${response.playground.embeddings ? `<div id="sb-playground-embeddings" class="sb-btn-text">${sb_('Embeddings')}</div>` : ``}`);
                        }
                    } else {
                        infoPanel('The playground is not working because multiple admin area instances are open. Close all others and keep only this one open.', 'alert');
                        console.error(response);
                    }
                    $(this).sbLoading(false);
                });
            }
        });

        $(chatbot_area).on('click', '#sb-playground-query', function () {
            infoPanel('<pre>' + JSON.stringify(SBApps.openAI.playground.last_response.query, null, 4).replaceAll('\\"', '"') + '</pre>', 'info', false, 'sb-playground-query-panel', false, true);
        });

        $(chatbot_area).on('click', '#sb-playground-embeddings', function () {
            let code = '';
            let embeddings = SBApps.openAI.playground.last_response.embeddings;
            for (var i = embeddings.length - 1; i > -1; i--) {
                code += `<span><b>${sb_('Source')}</b>: ${embeddings[i].source ? embeddings[i].source.autoLink({ target: '_blank' }) : ''}<br><b>${sb_('Score')}</b>: ${embeddings[i].score}<br><span>${embeddings[i].text}</span></span>`;
            }
            infoPanel(code, 'info', false, 'sb-playground-embeddings-panel', false, true);
        });

        $(chatbot_playground_editor).on('click', '[data-value="clear"]', function () {
            if (!loading(this)) {
                SBApps.openAI.playground.deleteData('delete', () => {
                    $(this).sbLoading(false);
                    chatbot_playground_area.html('');
                    chatbot_area.find('.sb-playground-info').html('');
                });
            }
        });

        $(chatbot_playground_editor).on('click', '[data-value="auto-clear"]', function () {
            $(this).toggleClass('sb-active');
        });

        $(chatbot_playground_editor).on('click', '[data-value="history"]', function () {
            let history = SBF.storage('playground-history');
            let code;
            if (history && history.length) {
                code = '';
                history.forEach((item) => {
                    code += `<li>${item}</li>`;
                });
            } else {
                code = `<p class="sb-no-results">${sb_('No results found.')}</p>`;
            }
            chatbot_playground_history_panel.find('ul').html(code);
            chatbot_playground_history_panel.toggleClass('sb-active');
        });

        $(chatbot_playground_history_panel).on('click', 'li', function () {
            chatbot_playground_editor.find('textarea').val($(this).text());
            chatbot_playground_history_panel.sbActive(false);
            chatbot_playground_editor.find('[data-value="send"]').click();
        });

        $(chatbot_playground_area).on('click', '.sb-icon-close', function () {
            if (!loading(this)) {
                let element = $(this).closest('[data-type]');
                SBApps.openAI.playground.deleteData('delete-message', () => {
                    $(this).sbLoading(false);
                    element.remove();
                }, element.attr('data-message-id'));
            }
        });

        $(chatbot_playground_area).on('click', '.sb-rich-chips .sb-btn', function () {
            chatbot_playground_editor.find('textarea').val($(this).html());
            chatbot_playground_editor.find('[data-value="send"]').click();
        });

        $(admin).on('click', '#open-ai-troubleshoot a, #google-troubleshoot a', function (e) {
            let id = $(this).parent().attr('id');
            e.preventDefault();
            if (id != 'google-troubleshoot' && ![true, 'mode'].includes(SBApps.openAI.troubleshoot())) {
                return false;
            }
            if (loading(this)) return;
            SBF.ajax({
                function: $(this).parent().attr('id')
            }, (response) => {
                if (response === true) {
                    infoBottom('Success. No issues found.');
                } else {
                    infoPanel(response);
                }
                $(this).sbLoading(false);
                $(conversations_area).find('.sb-admin-list .sb-select li.sb-active').click();
            });
            return false;
        });

        /*
        * ----------------------------------------------------------
        * Articles area
        * ----------------------------------------------------------
        */

        $(articles_area).on('click', '.ce-settings__button--delete.ce-settings__button--confirm', function () {
            let url = articles_area.find('.image-tool--filled img').attr('src');
            if (url) {
                SBF.ajax({ function: 'delete-file', path: url });
            }
        });

        $(articles_area).on('click', '.ul-articles li', function (e) {
            infoPanel('The changes will be lost.', 'alert', () => {
                SBArticles.show($(this).attr('data-id'));
                articles_area.find('.sb-scroll-area:not(.sb-nav)').scrollTop(0);
            }, false, false, false, !articles_save_required, () => {
                $(this).parent().find('li').sbActive(false);
                $(this).parent().find(`[data-id="${SBArticles.activeID()}"]`).sbActive(true);
            });
        });

        $(articles_area).on('click', '.ul-categories li', function (e) {
            SBArticles.categories.show($(this).attr('data-id'));
        });

        $(articles_area).on('click', '.sb-add-article', function () {
            SBArticles.add();
        });

        $(articles_area).on('click', '.sb-add-category', function () {
            SBArticles.categories.add();
        });

        $(articles_area).on('click', '.sb-nav i', function (e) {
            let parent = $(this).parent();
            let nav = parent.closest('ul');
            let is_category = nav.hasClass('ul-categories');
            infoPanel(`The ${is_category ? 'category' : 'article'} will be deleted permanently.`, 'alert', () => {
                let id = parent.attr('data-id');
                if (is_category) {
                    SBArticles.categories.delete(id);
                } else {
                    articles_area.find('#editorjs .image-tool__image-picture').each(function () {
                        SBF.ajax({ function: 'delete-file', path: $(this).attr('src') });
                    });
                    if (!id) {
                        return parent.remove();
                    }
                    loading(articles_content);
                    SBArticles.delete(id, (response) => {
                        articles_content.sbLoading(false);
                        editorJSDestroy();
                        if (nav.find('li').length > 1) {
                            setTimeout(() => {
                                if (parent.prev().length) {
                                    parent.prev().click();
                                } else {
                                    parent.next().click();
                                }
                                parent.remove();
                            }, 300);
                        }
                    });
                }
            });
            e.preventDefault();
            return false;
        });

        $(articles_area).on('click', '.sb-menu-wide li', function () {
            let type = $(this).data('type');
            if (type == 'settings') {
                SBSettings.open('articles', true);
            } else if (type == 'reports') {
                SBReports.open('articles');
            } else {
                articles_area.attr('data-type', type);
                SBArticles.categories.update();
            }
        });

        $(articles_area).on('click', '.sb-save-articles', function () {
            if (loading(this)) return;
            if (articles_area.attr('data-type') == 'categories') {
                SBArticles.categories.save((response) => {
                    $(this).sbLoading(false);
                });
            } else {
                SBArticles.save((response) => {
                    $(this).sbLoading(false);
                });
            }
        });

        $(articles_area).on('change input', 'input, textarea, select', function () {
            articles_save_required = true;
        });

        $(articles_category_select).on('change', function () {
            if (!articles_category_parent_select.val()) {
                infoBottom('Select a parent category first.', 'error');
                $(this).val('');
            }
        });

        /*
        * ----------------------------------------------------------
        * Reports area
        * ----------------------------------------------------------
        */

        $(reports_area).on('click', '.sb-open-report', function () {
            SBReports.openSingle($(this).closest('[data-report-name]').attr('data-report-name'));
        });

        $(reports_area).on('click', '.sb-select-reports ul [data-value]', function () {
            let id = $(this).attr('data-value');
            SBReports.active_report_category_name = false;
            reports_area.attr('class', 'sb-area-reports sb-active sb-report-' + id);
            SBReports.initReport(id, reports_area.find('#sb-date-picker').val());
            if (SBF.getURL('report') != id) {
                pushState('?report=' + id);
            }
        });

        $(reports_area).on('change', '#sb-date-picker', function () {
            SBReports.initReport(false, $(this).val());
        });

        $(admin).on('click', '#sb-export', function () {
            if (loading(this)) return;
            SBReports.export($(this).closest('[data-report-name]').attr('data-report-name'), (response) => {
                $(this).sbLoading(false);
                if (response) {
                    dialogDeleteFile(response, 'sb-export-report-close', 'Report exported')
                }
            });
        });

        if (SBF.getURL('report') && !reports_area.sbActive()) {
            header.find('.sb-admin-nav #sb-reports').click();
        }

        $(document).on('SBReportsLoaded', function () {
            let report_category_name = SBF.getURL('report') ? SBF.getURL('report') : SBReports.pending_open;
            if (report_category_name && SBReports.active_report_category_name != SBF.getURL('report')) {
                reports_area.find('[data-value="' + report_category_name + '"]').click();
                reports_area.find('.sb-select-reports ul').sbActive(false);
                SBReports.pending_open = false;
            }
        });

        /*
        * ----------------------------------------------------------
        * Woocommerce
        * ----------------------------------------------------------
        */

        // Panel reload button
        $(conversations_area).on('click', '.sb-panel-woocommerce > i', function () {
            SBApps.woocommerce.conversationPanel();
        });

        // Get order details
        $(conversations_area).on('click', '.sb-woocommerce-orders > div > span', function (e) {
            let parent = $(this).parent();
            if (!$(e.target).is('span')) return;
            if (!parent.sbActive()) {
                SBApps.woocommerce.conversationPanelOrder(parent.attr('data-id'));
            }
        });

        // Products popup 
        $(conversations_area).on('click', '.sb-btn-woocommerce', function () {
            if (woocommerce_products_box_ul.sbLoading() || (activeUser() != false && activeUser().language != SBApps.itemsPanel.panel_language)) {
                SBApps.itemsPanel.populate('woocommerce');
            }
            woocommerce_products_box.find('.sb-search-btn').sbActive(true).find('input').get(0).focus();
            woocommerce_products_box.sbTogglePopup(this);
        });

        // Products popup pagination
        $(woocommerce_products_box).find('.sb-woocommerce-products-list').on('scroll', function () {
            if (scrollPagination(this, true)) {
                SBApps.itemsPanel.pagination(this, 'woocommerce');
            }
        });

        // Products popup filter
        $(woocommerce_products_box).on('click', '.sb-select li', function () {
            SBApps.itemsPanel.filter(this, 'woocommerce');
        });

        // Products popup search
        $(woocommerce_products_box).on('input', '.sb-search-btn input', function () {
            SBApps.itemsPanel.search(this, 'woocommerce');
        });

        $(woocommerce_products_box).on('click', '.sb-search-btn i', function () {
            SBF.searchClear(this, () => { SBApps.itemsPanel.search($(this).next(), 'woocommerce') });
        });

        // Cart popup insert product
        $(woocommerce_products_box).on('click', '.sb-woocommerce-products-list li', function () {
            let action = woocommerce_products_box.attr('data-action');
            let id = $(this).data('id');
            if (SBF.null(action)) {
                SBChat.insertText(`{product_card id="${id}"}`);
            } else {
                woocommerce_products_box_ul.sbLoading(true);
                conversations_area.find('.sb-add-cart-btn').sbLoading(true);
                SBChat.sendMessage(-1, '', [], (response) => {
                    if (response) {
                        SBApps.woocommerce.conversationPanelUpdate(id);
                        admin.sbHideLightbox();
                    }
                }, { 'event': 'woocommerce-update-cart', 'action': 'cart-add', 'id': id });
            }
            SBF.deactivateAll();
            admin.removeClass('sb-popup-active');
        });

        // Cart add product
        $(conversations_area).on('click', '.sb-panel-woocommerce .sb-add-cart-btn', function () {
            if (loading(this)) return;
            if (SBChat.user_online) {
                SBApps.itemsPanel.populate('woocommerce');
                woocommerce_products_box.sbShowLightbox(true, 'cart-add');
            } else {
                infoPanel('The user is offline. Only the carts of online users can be updated.');
            }
        });

        // Cart remove product
        $(conversations_area).on('click', '.sb-panel-woocommerce .sb-list-items > a > i', function (e) {
            let id = $(this).parent().attr('data-id');
            SBChat.sendMessage(-1, '', [], () => {
                SBApps.woocommerce.conversationPanelUpdate(id, 'removed');
            }, { event: 'woocommerce-update-cart', action: 'cart-remove', id: id });
            $(this).sbLoading(true);
            e.preventDefault();
            return false;
        });

        /*
        * ----------------------------------------------------------
        * Apps and integrations
        * ----------------------------------------------------------
        */

        // Calendar
        $(conversations_area).on('click', '.sb-integration-calendar-cancel', function (e) {
            infoPanel('The booking will be cancelled.', 'alert', () => {
                if (loading(this)) return;
                SBApps.calendar.cancelBooking($(this).parent().attr('data-id'), (response) => {
                    if (response === true) {
                        $(this).parent().remove();
                        infoBottom('Booking cancelled.');
                    }
                });
            });
            e.preventDefault();
            return false;
        });

        $(conversations_area).on('click', '.sb-panel-calendar > i', function () {
            SBSettings.loadDatePicker(() => {
                SBAdmin.genericPanel('calendar', 'Booking', '<input type="text"><div class="sb-split"><div id="sb-calendar-cnt"></div><div id="sb-slot-list"></div></div>', ['Add booking'], '', true);
                admin.find('.sb-calendar-box input').daterangepicker({ ...SBSettings.getDatePickerSettings(true, true), ...{ parentEl: '#sb-calendar-cnt' } }).click();
            });
        });

        $(admin).on('change', '.sb-calendar-box input', function () {
            let list = admin.find('#sb-slot-list');
            list.html('').sbLoading(true);
            SBApps.calendar.getAvailableSlots($(this).val(), (response) => {
                let code = '';
                if (response) {
                    response.forEach((slot) => {
                        code += `<div data-id="${slot}">${slot}</div>`;
                    });
                }
                list.html(code ? code : `<p class="sb-no-results">${sb_('No results found.')}</p>`).sbLoading(false);
            });
        });

        $(admin).on('click', '#sb-add-booking', function () {
            let slot = admin.find('#sb-slot-list .sb-active').attr('data-id');
            let info = admin.find('.sb-calendar-box .sb-info');
            info.html('').sbActive(false);
            if (!slot || loading(this)) {
                return;
            }
            SBApps.calendar.addBooking(admin.find('.sb-calendar-box input').val() + ' ' + slot, (response) => {
                $(this).sbLoading(false);
                if (response === true) {
                    infoBottom('Booking successfully created.');
                    SBApps.calendar.conversationPanel();
                    admin.sbHideLightbox();
                } else {
                    admin.find('.sb-calendar-box .sb-info').html(response).sbActive(true);
                }
            });
        });

        $(admin).on('click', '#sb-slot-list > div', function () {
            $(this).siblings().sbActive(false);
            $(this).toggleClass('sb-active');
        });

        // Ump
        $(conversations_area).on('click', '.sb-panel-ump > i', function () {
            SBApps.ump.conversationPanel();
        });

        // ARMember
        $(conversations_area).on('click', '.sb-panel-armember > i', function () {
            SBApps.armember.conversationPanel();
        });

        // OpenCart
        $(conversations_area).on('click', '.sb-panel-opencart > i', function () {
            SBApps.opencart.conversationPanel();
        });

        $(conversations_area).on('click', '.sb-opencart-orders > a', function () {
            SBApps.opencart.openOrder($(this).attr('data-id'));
        });

        $(settings_area).on('click', '#opencart-sync a', function (e) {
            e.preventDefault();
            if (loading(this)) return;
            SBF.ajax({
                function: 'opencart-sync'
            }, (response) => {
                $(this).sbLoading(false);
                infoPanel(response === true ? 'Users successfully imported.' : response);
            });
        });

        // Perfex, whmcs, aecommerce
        $(settings_area).on('click', '#perfex-sync a, #whmcs-sync a, #perfex-articles-sync a, #whmcs-articles-sync a, #aecommerce-sync a, #aecommerce-sync-admins a, #aecommerce-sync-sellers a, #martfury-sync a, #martfury-sync-sellers a', function (e) {
            if (loading(this)) return;
            let function_name = $(this).closest('[id]').attr('id');
            let articles = function_name.indexOf('article') > 0;
            SBF.ajax({
                function: function_name
            }, (response) => {
                if (response === true) {
                    if (!articles) {
                        SBUsers.update();
                    }
                    infoPanel(articles ? 'Articles successfully imported.' : 'Users successfully imported.');
                } else {
                    infoPanel('Error. Response: ' + JSON.stringify(response));
                }
                $(this).sbLoading(false);
            });
            e.preventDefault();
        });

        // Zendesk
        $(conversations_area).on('click', '#sb-zendesk-btn', function (e) {
            if (loading(this)) return;
            SBF.ajax({
                function: 'zendesk-create-ticket',
                conversation_id: SBChat.conversation.id
            }, (response) => {
                if (response === true) {
                    SBApps.zendesk.conversationPanel();
                } else {
                    infoPanel('Error. Response: ' + JSON.stringify(response));
                }
                $(this).sbLoading(false);
            });
            e.preventDefault();
        });

        $(conversations_area).on('click', '#sb-zendesk-update-ticket', function (e) {
            if (loading(this)) return;
            SBF.ajax({
                function: 'zendesk-update-ticket',
                conversation_id: SBChat.conversation.id,
                zendesk_ticket_id: $(this).closest('[data-id]').attr('data-id')
            }, () => {
                $(this).sbLoading(false);
            });
            e.preventDefault();
            return false;
        });

        /*
        * ----------------------------------------------------------
        * Miscellaneous
        * ----------------------------------------------------------
        */

        $(admin).on('click', '[data-id="rating"]', function () {
            SBConversations.highlightMessage($(this).attr('data-message-id'));
        });

        $(admin).on('click', '.sb-enlarger', function () {
            $(this).sbActive(true);
        });

        $(admin).on('mouseenter', '[data-sb-tooltip-init]', function () {
            $(this).parent().sbInitTooltips();
            $(this).removeAttr('data-sb-tooltip-init');
            $(this).trigger('mouseenter');
        });

        // Language switcher
        $(admin).on('click', '.sb-language-switcher > i', function () {
            let switcher = $(this).parent();
            let active_languages = switcher.find('[data-language]').map(function () { return $(this).attr('data-language') }).get();
            let code = '';
            active_languages.push('en');
            for (var key in SB_LANGUAGE_CODES) {
                if (!active_languages.includes(key)) {
                    code += `<div data-language="${key}"><img src="${SB_URL}/media/flags/${key}.png" />${sb_(SB_LANGUAGE_CODES[key])}</div>`;
                }
            }
            language_switcher_target = switcher;
            SBAdmin.genericPanel('languages', 'Choose a language', code, [], ' data-source="' + switcher.attr('data-source') + '"', true);
        });

        $(admin).on('click', '.sb-language-switcher img', function () {
            let item = $(this).parent();
            let active = item.sbActive();
            let language = active ? false : item.attr('data-language');
            switch (item.parent().attr('data-source')) {
                case 'article-categories':
                    SBArticles.categories.show(SBArticles.categories.activeID(), language);
                    break;
                case 'articles':
                    let previous_active = articles_content.find('.sb-language-switcher .sb-active');
                    infoPanel('The changes will be lost.', 'alert', () => {
                        let id = item.attr('data-id');
                        if (!id && !active) {
                            SBArticles.clear();
                        } else {
                            SBArticles.show(id && !active ? id : SBArticles.activeID(true));
                        }
                    }, false, false, false, !articles_save_required, () => {
                        item.sbActive(false);
                        previous_active.sbActive(true);
                    });
                    break;
                case 'automations':
                    SBSettings.automations.show(false, language);
                    break;
                case 'settings':
                    let active_language = item.parent().find('[data-language].sb-active');
                    SBSettings.translations.save(item, active ? item.attr('data-language') : (active_language.length ? active_language.attr('data-language') : false));
                    SBSettings.translations.activate(item, language);
                    break;
            }
            item.siblings().sbActive(false);
            item.sbActive(!active);
        });

        $(admin).on('click', '.sb-language-switcher span > i', function () {
            let item = $(this).parent();
            let language = item.attr('data-language');
            infoPanel(sb_('The {T} translation will be deleted.').replace('{T}', sb_(SB_LANGUAGE_CODES[language])), 'alert', () => {
                switch (item.parent().attr('data-source')) {
                    case 'article-categories':
                        SBArticles.categories.translations.delete(language);
                        break;
                    case 'articles':
                        SBArticles.translations.delete(language);
                        break;
                    case 'automations':
                        SBSettings.automations.deleteTranslation(false, language);
                        SBSettings.automations.show();
                        break;
                    case 'settings':
                        SBSettings.translations.delete(item, language);
                        break;
                }
                item.remove();
            });
        });

        $(admin).on('click', '.sb-languages-box [data-language]', function () {
            let box = $(this).parents().eq(1);
            let language = $(this).attr('data-language');
            let hide = true;
            switch (box.attr('data-source')) {
                case 'article-categories':
                    SBArticles.categories.translations.add(language);
                    break;
                case 'articles':
                    infoPanel('The changes will be lost.', 'alert', () => {
                        SBArticles.translations.add(language);
                        admin.sbHideLightbox();
                    }, false, false, false, !articles_save_required);
                    hide = false;
                    break;
                case 'automations':
                    SBSettings.automations.addTranslation(false, false, language);
                    SBSettings.automations.show(false, language);
                    break;
                case 'settings':
                    SBSettings.translations.add(language);
                    break;
            }
            if (hide) {
                admin.sbHideLightbox();
            }
        });

        // Lightbox
        $(admin).on('click', '.sb-lightbox .sb-top-bar .sb-close', function () {
            admin.sbHideLightbox();
            if ($(this).closest('.sb-lightbox').parent().attr('id') == 'sb-generic-panel') {
                $(this).closest('.sb-lightbox').html('');
            }
        });

        $(admin).on('click', '.sb-lightbox .sb-info', function () {
            $(this).sbActive(false);
        });

        // Alert and information box
        $(admin).on('click', '.sb-dialog-box a', function () {
            let lightbox = $(this).closest('.sb-lightbox');
            if ($(this).hasClass('sb-confirm')) {
                alertOnConfirmation();
            }
            if ($(this).hasClass('sb-cancel') && alertOnCancel) {
                alertOnCancel();
            }
            if (admin.find('.sb-lightbox.sb-active').length == 1) {
                overlay.sbActive(false);
            }
            SBAdmin.open_popup = false;
            lightbox.sbActive(false);
        });

        $(admin).on('click', '.sb-menu-wide li, .sb-nav li', function () {
            $(this).siblings().sbActive(false);
            $(this).sbActive(true);
        });

        $(admin).on('click', '.sb-nav:not(.sb-nav-only) li:not(.sb-tab-nav-title)', function () {
            let area = $(this).closest('.sb-tab');
            let tab = $(area).find(' > .sb-content > div').sbActive(false).eq($(this).parent().find('li:not(.sb-tab-nav-title)').index(this));
            tab.sbActive(true);
            tab.find('textarea').each(function () {
                $(this).autoExpandTextarea();
                $(this).manualExpandTextarea();
            });
            area.find('.sb-scroll-area:not(.sb-nav)').scrollTop(0);
        });

        $(admin).sbInitTooltips();

        $(admin).on('click', '[data-button="toggle"]', function () {
            let show = admin.find('.' + $(this).data('show'));
            let hide = admin.find('.' + $(this).data('hide'));
            show.addClass('sb-show-animation').show();
            hide.hide();
            SBAdmin.open_popup = show.hasClass('sb-lightbox') || show.hasClass('sb-popup') ? show : false;
        });

        $(admin).on('click', '.sb-info-card', function () {
            $(this).sbActive(false);
        });

        $(upload_input).on('change', function () {
            if (upload_function) {
                upload_function();
                upload_function = false;
            } else {
                $(upload_target).sbLoading($(this).prop('files').length);
                $(this).sbUploadFiles((response) => {
                    $(upload_target).sbLoading(false);
                    response = JSON.parse(response);
                    if (response[0] == 'success') {
                        let type = $(upload_target).closest('[data-type]').data('type');
                        if (type == 'upload-image') {
                            if ($(upload_target).attr('data-value')) {
                                SBF.ajax({ function: 'delete-file', path: $(upload_target).attr('data-value') });
                            }
                            $(upload_target).attr('data-value', response[1]).css('background-image', `url("${response[1]}")`);
                        }
                        if (upload_on_success) {
                            upload_on_success(response[1]);
                        }
                    } else {
                        console.log(response[1]);
                    }
                });
            }
        });

        $(admin).on('click', '.sb-accordion > div > span', function (e) {
            let parent = $(this).parent();
            let active = $(parent).sbActive();
            if (!$(e.target).is('span')) return;
            parent.siblings().sbActive(false);
            parent.sbActive(!active);
        });

        $(admin).on('mousedown', function (e) {
            if ($(SBAdmin.open_popup).length) {
                let popup = $(SBAdmin.open_popup);
                if (!popup.is(e.target) && popup.has(e.target).length === 0 && !['sb-btn-saved-replies', 'sb-btn-emoji', 'sb-btn-woocommerce', 'sb-btn-shopify', 'sb-btn-open-ai'].includes($(e.target).attr('class'))) {
                    if (popup.hasClass('sb-popup')) {
                        popup.sbTogglePopup();
                    } else if (popup.hasClass('sb-select')) {
                        popup.find('ul').sbActive(false);
                    } else if (popup.hasClass('sb-menu-mobile')) {
                        popup.find('i').sbActive(false);
                    } else if (popup.hasClass('sb-menu')) {
                        popup.sbActive(false);
                    } else if (!SBAdmin.open_popup || !['sb-embeddings-box'].includes(SBAdmin.open_popup.attr('id'))) {
                        admin.sbHideLightbox();
                    }
                    SBAdmin.open_popup = false;
                }
            }
        });
    });

    function initialization() {
        SBF.ajax({
            function: 'get-conversations'
        }, (response) => {
            if (!response.length) {
                conversations_area.find('.sb-board').addClass('sb-no-conversation');
            }
            SBConversations.populateList(response);
            if (responsive) {
                conversations_area.find('.sb-admin-list').sbActive(true);
            }
            if (SBF.getURL('conversation')) {
                if (!conversations_area.sbActive()) {
                    header.find('.sb-admin-nav #sb-conversations').click();
                }
                SBConversations.openConversation(SBF.getURL('conversation'));
            } else if (!responsive && !SBF.getURL('user') && !SBF.getURL('setting') && !SBF.getURL('report') && (!SBF.getURL('area') || SBF.getURL('area') == 'conversations')) {
                setTimeout(() => {
                    SBConversations.clickFirst();
                }, 100);
            }
            SBConversations.startRealTime();
            SBConversations.datetime_last_conversation = SB_ADMIN_SETTINGS.now_db;
            loadingGlobal(false);
        });
        SBF.serviceWorker.init();
        if (SB_ADMIN_SETTINGS.push_notifications) {
            SBF.serviceWorker.initPushNotifications();
        }
        setInterval(function () {
            SBF.ajax({
                function: 'get-active-user',
                db: true
            }, (response) => {
                if (!response) SBF.reset();
            });
        }, 3600000);
    }
}(jQuery));

// tinyColorPicker v1.1.1 2016-08-30 

!function (a, b) { "object" == typeof exports ? module.exports = b(a) : "function" == typeof define && define.amd ? define("colors", [], function () { return b(a) }) : a.Colors = b(a) }(this, function (a, b) { "use strict"; function c(a, c, d, f, g) { if ("string" == typeof c) { var c = v.txt2color(c); d = c.type, p[d] = c[d], g = g !== b ? g : c.alpha } else if (c) for (var h in c) a[d][h] = k(c[h] / l[d][h][1], 0, 1); return g !== b && (a.alpha = k(+g, 0, 1)), e(d, f ? a : b) } function d(a, b, c) { var d = o.options.grey, e = {}; return e.RGB = { r: a.r, g: a.g, b: a.b }, e.rgb = { r: b.r, g: b.g, b: b.b }, e.alpha = c, e.equivalentGrey = n(d.r * a.r + d.g * a.g + d.b * a.b), e.rgbaMixBlack = i(b, { r: 0, g: 0, b: 0 }, c, 1), e.rgbaMixWhite = i(b, { r: 1, g: 1, b: 1 }, c, 1), e.rgbaMixBlack.luminance = h(e.rgbaMixBlack, !0), e.rgbaMixWhite.luminance = h(e.rgbaMixWhite, !0), o.options.customBG && (e.rgbaMixCustom = i(b, o.options.customBG, c, 1), e.rgbaMixCustom.luminance = h(e.rgbaMixCustom, !0), o.options.customBG.luminance = h(o.options.customBG, !0)), e } function e(a, b) { var c, e, k, q = b || p, r = v, s = o.options, t = l, u = q.RND, w = "", x = "", y = { hsl: "hsv", rgb: a }, z = u.rgb; if ("alpha" !== a) { for (var A in t) if (!t[A][A]) { a !== A && (x = y[A] || "rgb", q[A] = r[x + "2" + A](q[x])), u[A] || (u[A] = {}), c = q[A]; for (w in c) u[A][w] = n(c[w] * t[A][w][1]) } z = u.rgb, q.HEX = r.RGB2HEX(z), q.equivalentGrey = s.grey.r * q.rgb.r + s.grey.g * q.rgb.g + s.grey.b * q.rgb.b, q.webSave = e = f(z, 51), q.webSmart = k = f(z, 17), q.saveColor = z.r === e.r && z.g === e.g && z.b === e.b ? "web save" : z.r === k.r && z.g === k.g && z.b === k.b ? "web smart" : "", q.hueRGB = v.hue2RGB(q.hsv.h), b && (q.background = d(z, q.rgb, q.alpha)) } var B, C, D, E = q.rgb, F = q.alpha, G = "luminance", H = q.background; return B = i(E, { r: 0, g: 0, b: 0 }, F, 1), B[G] = h(B, !0), q.rgbaMixBlack = B, C = i(E, { r: 1, g: 1, b: 1 }, F, 1), C[G] = h(C, !0), q.rgbaMixWhite = C, s.customBG && (D = i(E, H.rgbaMixCustom, F, 1), D[G] = h(D, !0), D.WCAG2Ratio = j(D[G], H.rgbaMixCustom[G]), q.rgbaMixBGMixCustom = D, D.luminanceDelta = m.abs(D[G] - H.rgbaMixCustom[G]), D.hueDelta = g(H.rgbaMixCustom, D, !0)), q.RGBLuminance = h(z), q.HUELuminance = h(q.hueRGB), s.convertCallback && s.convertCallback(q, a), q } function f(a, b) { var c = {}, d = 0, e = b / 2; for (var f in a) d = a[f] % b, c[f] = a[f] + (d > e ? b - d : -d); return c } function g(a, b, c) { return (m.max(a.r - b.r, b.r - a.r) + m.max(a.g - b.g, b.g - a.g) + m.max(a.b - b.b, b.b - a.b)) * (c ? 255 : 1) / 765 } function h(a, b) { for (var c = b ? 1 : 255, d = [a.r / c, a.g / c, a.b / c], e = o.options.luminance, f = d.length; f--;)d[f] = d[f] <= .03928 ? d[f] / 12.92 : m.pow((d[f] + .055) / 1.055, 2.4); return e.r * d[0] + e.g * d[1] + e.b * d[2] } function i(a, c, d, e) { var f = {}, g = d !== b ? d : 1, h = e !== b ? e : 1, i = g + h * (1 - g); for (var j in a) f[j] = (a[j] * g + c[j] * h * (1 - g)) / i; return f.a = i, f } function j(a, b) { var c = 1; return c = a >= b ? (a + .05) / (b + .05) : (b + .05) / (a + .05), n(100 * c) / 100 } function k(a, b, c) { return a > c ? c : b > a ? b : a } var l = { rgb: { r: [0, 255], g: [0, 255], b: [0, 255] }, hsv: { h: [0, 360], s: [0, 100], v: [0, 100] }, hsl: { h: [0, 360], s: [0, 100], l: [0, 100] }, alpha: { alpha: [0, 1] }, HEX: { HEX: [0, 16777215] } }, m = a.Math, n = m.round, o = {}, p = {}, q = { r: .298954, g: .586434, b: .114612 }, r = { r: .2126, g: .7152, b: .0722 }, s = function (a) { this.colors = { RND: {} }, this.options = { color: "rgba(0,0,0,0)", grey: q, luminance: r, valueRanges: l }, t(this, a || {}) }, t = function (a, d) { var e, f = a.options; u(a); for (var g in d) d[g] !== b && (f[g] = d[g]); e = f.customBG, f.customBG = "string" == typeof e ? v.txt2color(e).rgb : e, p = c(a.colors, f.color, b, !0) }, u = function (a) { o !== a && (o = a, p = a.colors) }; s.prototype.setColor = function (a, d, f) { return u(this), a ? c(this.colors, a, d, b, f) : (f !== b && (this.colors.alpha = k(f, 0, 1)), e(d)) }, s.prototype.setCustomBackground = function (a) { return u(this), this.options.customBG = "string" == typeof a ? v.txt2color(a).rgb : a, c(this.colors, b, "rgb") }, s.prototype.saveAsBackground = function () { return u(this), c(this.colors, b, "rgb", !0) }, s.prototype.toString = function (a, b) { return v.color2text((a || "rgb").toLowerCase(), this.colors, b) }; var v = { txt2color: function (a) { var b = {}, c = a.replace(/(?:#|\)|%)/g, "").split("("), d = (c[1] || "").split(/,\s*/), e = c[1] ? c[0].substr(0, 3) : "rgb", f = ""; if (b.type = e, b[e] = {}, c[1]) for (var g = 3; g--;)f = e[g] || e.charAt(g), b[e][f] = +d[g] / l[e][f][1]; else b.rgb = v.HEX2rgb(c[0]); return b.alpha = d[3] ? +d[3] : 1, b }, color2text: function (a, b, c) { var d = c !== !1 && n(100 * b.alpha) / 100, e = "number" == typeof d && c !== !1 && (c || 1 !== d), f = b.RND.rgb, g = b.RND.hsl, h = "hex" === a && e, i = "hex" === a && !h, j = "rgb" === a || h, k = j ? f.r + ", " + f.g + ", " + f.b : i ? "#" + b.HEX : g.h + ", " + g.s + "%, " + g.l + "%"; return i ? k : (h ? "rgb" : a) + (e ? "a" : "") + "(" + k + (e ? ", " + d : "") + ")" }, RGB2HEX: function (a) { return ((a.r < 16 ? "0" : "") + a.r.toString(16) + (a.g < 16 ? "0" : "") + a.g.toString(16) + (a.b < 16 ? "0" : "") + a.b.toString(16)).toUpperCase() }, HEX2rgb: function (a) { return a = a.split(""), { r: +("0x" + a[0] + a[a[3] ? 1 : 0]) / 255, g: +("0x" + a[a[3] ? 2 : 1] + (a[3] || a[1])) / 255, b: +("0x" + (a[4] || a[2]) + (a[5] || a[2])) / 255 } }, hue2RGB: function (a) { var b = 6 * a, c = ~~b % 6, d = 6 === b ? 0 : b - c; return { r: n(255 * [1, 1 - d, 0, 0, d, 1][c]), g: n(255 * [d, 1, 1, 1 - d, 0, 0][c]), b: n(255 * [0, 0, d, 1, 1, 1 - d][c]) } }, rgb2hsv: function (a) { var b, c, d, e = a.r, f = a.g, g = a.b, h = 0; return g > f && (f = g + (g = f, 0), h = -1), c = g, f > e && (e = f + (f = e, 0), h = -2 / 6 - h, c = m.min(f, g)), b = e - c, d = e ? b / e : 0, { h: 1e-15 > d ? p && p.hsl && p.hsl.h || 0 : b ? m.abs(h + (f - g) / (6 * b)) : 0, s: e ? b / e : p && p.hsv && p.hsv.s || 0, v: e } }, hsv2rgb: function (a) { var b = 6 * a.h, c = a.s, d = a.v, e = ~~b, f = b - e, g = d * (1 - c), h = d * (1 - f * c), i = d * (1 - (1 - f) * c), j = e % 6; return { r: [d, h, g, g, i, d][j], g: [i, d, d, h, g, g][j], b: [g, g, i, d, d, h][j] } }, hsv2hsl: function (a) { var b = (2 - a.s) * a.v, c = a.s * a.v; return c = a.s ? 1 > b ? b ? c / b : 0 : c / (2 - b) : 0, { h: a.h, s: a.v || c ? c : p && p.hsl && p.hsl.s || 0, l: b / 2 } }, rgb2hsl: function (a, b) { var c = v.rgb2hsv(a); return v.hsv2hsl(b ? c : p.hsv = c) }, hsl2rgb: function (a) { var b = 6 * a.h, c = a.s, d = a.l, e = .5 > d ? d * (1 + c) : d + c - c * d, f = d + d - e, g = e ? (e - f) / e : 0, h = ~~b, i = b - h, j = e * g * i, k = f + j, l = e - j, m = h % 6; return { r: [e, l, f, f, k, e][m], g: [k, e, e, l, f, f][m], b: [f, f, k, e, e, l][m] } } }; return s }), function (a, b) { "object" == typeof exports ? module.exports = b(a, require("jquery"), require("colors")) : "function" == typeof define && define.amd ? define(["jquery", "colors"], function (c, d) { return b(a, c, d) }) : b(a, a.jQuery, a.Colors) }(this, function (a, b, c, d) { "use strict"; function e(a) { return a.value || a.getAttribute("value") || b(a).css("background-color") || "#FFF" } function f(a) { return a = a.originalEvent && a.originalEvent.touches ? a.originalEvent.touches[0] : a, a.originalEvent ? a.originalEvent : a } function g(a) { return b(a.find(r.doRender)[0] || a[0]) } function h(c) { var d = b(this), f = d.offset(), h = b(a), k = r.gap; c ? (s = g(d), s._colorMode = s.data("colorMode"), p.$trigger = d, (t || i()).css(r.positionCallback.call(p, d) || { left: (t._left = f.left) - ((t._left += t._width - (h.scrollLeft() + h.width())) + k > 0 ? t._left + k : 0), top: (t._top = f.top + d.outerHeight()) - ((t._top += t._height - (h.scrollTop() + h.height())) + k > 0 ? t._top + k : 0) }).show(r.animationSpeed, function () { c !== !0 && (y.toggle(!!r.opacity)._width = y.width(), v._width = v.width(), v._height = v.height(), u._height = u.height(), q.setColor(e(s[0])), n(!0)) }).off(".tcp").on(D, ".cp-xy-slider,.cp-z-slider,.cp-alpha", j)) : p.$trigger && b(t).hide(r.animationSpeed, function () { n(!1), p.$trigger = null }).off(".tcp") } function i() { return b("head")[r.cssPrepend ? "prepend" : "append"]('<style type="text/css" id="tinyColorPickerStyles">' + (r.css || I) + (r.cssAddon || "") + "</style>"), b(H).css({ margin: r.margin }).appendTo("body").show(0, function () { p.$UI = t = b(this), F = r.GPU && t.css("perspective") !== d, u = b(".cp-z-slider", this), v = b(".cp-xy-slider", this), w = b(".cp-xy-cursor", this), x = b(".cp-z-cursor", this), y = b(".cp-alpha", this), z = b(".cp-alpha-cursor", this), r.buildCallback.call(p, t), t.prepend("<div>").children().eq(0).css("width", t.children().eq(0).width()), t._width = this.offsetWidth, t._height = this.offsetHeight }).hide() } function j(a) { var c = this.className.replace(/cp-(.*?)(?:\s*|$)/, "$1").replace("-", "_"); (a.button || a.which) > 1 || (a.preventDefault && a.preventDefault(), a.returnValue = !1, s._offset = b(this).offset(), (c = "xy_slider" === c ? k : "z_slider" === c ? l : m)(a), n(), A.on(E, function () { A.off(".tcp") }).on(C, function (a) { c(a), n() })) } function k(a) { var b = f(a), c = b.pageX - s._offset.left, d = b.pageY - s._offset.top; q.setColor({ s: c / v._width * 100, v: 100 - d / v._height * 100 }, "hsv") } function l(a) { var b = f(a).pageY - s._offset.top; q.setColor({ h: 360 - b / u._height * 360 }, "hsv") } function m(a) { var b = f(a).pageX - s._offset.left, c = b / y._width; q.setColor({}, "rgb", c) } function n(a) { var b = q.colors, c = b.hueRGB, e = (b.RND.rgb, b.RND.hsl, r.dark), f = r.light, g = q.toString(s._colorMode, r.forceAlpha), h = b.HUELuminance > .22 ? e : f, i = b.rgbaMixBlack.luminance > .22 ? e : f, j = (1 - b.hsv.h) * u._height, k = b.hsv.s * v._width, l = (1 - b.hsv.v) * v._height, m = b.alpha * y._width, n = F ? "translate3d" : "", p = s[0].value, t = s[0].hasAttribute("value") && "" === p && a !== d; v._css = { backgroundColor: "rgb(" + c.r + "," + c.g + "," + c.b + ")" }, w._css = { transform: n + "(" + k + "px, " + l + "px, 0)", left: F ? "" : k, top: F ? "" : l, borderColor: b.RGBLuminance > .22 ? e : f }, x._css = { transform: n + "(0, " + j + "px, 0)", top: F ? "" : j, borderColor: "transparent " + h }, y._css = { backgroundColor: "#" + b.HEX }, z._css = { transform: n + "(" + m + "px, 0, 0)", left: F ? "" : m, borderColor: i + " transparent" }, s._css = { backgroundColor: t ? "" : g, color: t ? "" : b.rgbaMixBGMixCustom.luminance > .22 ? e : f }, s.text = t ? "" : p !== g ? g : "", a !== d ? o(a) : G(o) } function o(a) { v.css(v._css), w.css(w._css), x.css(x._css), y.css(y._css), z.css(z._css), r.doRender && s.css(s._css), s.text && s.val(s.text), r.renderCallback.call(p, s, "boolean" == typeof a ? a : d) } var p, q, r, s, t, u, v, w, x, y, z, A = b(document), B = b(), C = "touchmove.tcp mousemove.tcp pointermove.tcp", D = "touchstart.tcp mousedown.tcp pointerdown.tcp", E = "touchend.tcp mouseup.tcp pointerup.tcp", F = !1, G = a.requestAnimationFrame || a.webkitRequestAnimationFrame || function (a) { a() }, H = '<div class="cp-color-picker"><div class="cp-z-slider"><div class="cp-z-cursor"></div></div><div class="cp-xy-slider"><div class="cp-white"></div><div class="cp-xy-cursor"></div></div><div class="cp-alpha"><div class="cp-alpha-cursor"></div></div></div>', I = ".cp-color-picker{position:absolute;overflow:hidden;padding:6px 6px 0;background-color:#444;color:#bbb;font-family:Arial,Helvetica,sans-serif;font-size:12px;font-weight:400;cursor:default;border-radius:5px}.cp-color-picker>div{position:relative;overflow:hidden}.cp-xy-slider{float:left;height:128px;width:128px;margin-bottom:6px;background:linear-gradient(to right,#FFF,rgba(255,255,255,0))}.cp-white{height:100%;width:100%;background:linear-gradient(rgba(0,0,0,0),#000)}.cp-xy-cursor{position:absolute;top:0;width:10px;height:10px;margin:-5px;border:1px solid #fff;border-radius:100%;box-sizing:border-box}.cp-z-slider{float:right;margin-left:6px;height:128px;width:20px;background:linear-gradient(red 0,#f0f 17%,#00f 33%,#0ff 50%,#0f0 67%,#ff0 83%,red 100%)}.cp-z-cursor{position:absolute;margin-top:-4px;width:100%;border:4px solid #fff;border-color:transparent #fff;box-sizing:border-box}.cp-alpha{clear:both;width:100%;height:16px;margin:6px 0;background:linear-gradient(to right,#444,rgba(0,0,0,0))}.cp-alpha-cursor{position:absolute;margin-left:-4px;height:100%;border:4px solid #fff;border-color:#fff transparent;box-sizing:border-box}", J = function (a) { q = this.color = new c(a), r = q.options, p = this }; J.prototype = { render: n, toggle: h }, b.fn.colorPicker = function (c) { var d = this, f = function () { }; return c = b.extend({ animationSpeed: 150, GPU: !0, doRender: !0, customBG: "#FFF", opacity: !0, renderCallback: f, buildCallback: f, positionCallback: f, body: document.body, scrollResize: !0, gap: 4, dark: "#222", light: "#DDD" }, c), !p && c.scrollResize && b(a).on("resize.tcp scroll.tcp", function () { p.$trigger && p.toggle.call(p.$trigger[0], !0) }), B = B.add(this), this.colorPicker = p || new J(c), this.options = c, b(c.body).off(".tcp").on(D, function (a) { -1 === B.add(t).add(b(t).find(a.target)).index(a.target) && h() }), this.on("focusin.tcp click.tcp", function (a) { p.color.options = b.extend(p.color.options, r = d.options), h.call(this, a) }).on("change.tcp", function () { q.setColor(this.value || "#FFF"), d.colorPicker.render(!0) }).each(function () { var a = e(this), d = a.split("("), f = g(b(this)); f.data("colorMode", d[1] ? d[0].substr(0, 3) : "HEX").attr("readonly", r.preventFocus), c.doRender && f.css({ "background-color": a, color: function () { return q.setColor(a).rgbaMixBGMixCustom.luminance > .22 ? c.dark : c.light } }) }) }, b.fn.colorPicker.destroy = function () { b("*").off(".tcp"), p.toggle(!1), B = b() } });