function createCookie(name, value, day = 7) {
    let expires = new Date()
    expires.setTime(expires.getTime() + (day * 24 * 60 * 60 * 1000))

    document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + expires.toUTCString() + "; path=/"
}

function getCookie(name) {
    let cookieString = document.cookie
    let cookies = cookieString.split(';')

    for (let i = 0; i < cookies.length; i++) {
        let cookie = cookies[i].trim()

        if (cookie.startsWith(name + '=')) {
            let value = cookie.substring(name.length + 1)
            return decodeURIComponent(value)
        }
    }

    return null;
}

function arraysAreEqual(arr1, arr2) {
    if (arr1.length !== arr2.length) {
        return false
    }
    arr1.sort()
    arr2.sort()

    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            return false
        }
    }

    return true
}

function chart(ref = 'chart', data = [], labels = []) {
    return {
        chart: null,
        init() {
            const gridBorderColor = this.activeTheme === 'dark' ? "#2b2b2b" : "rgb(226 232 240)"
            const borderColor = "#255aef"

            let chartSelect = document.getElementById(ref)

            this.chart = new Chart(chartSelect, {
                type: "line",
                options: {
                    responsive: true,
                    scales: {
                        xAxes: [{
                            gridLines: {
                                display: true,
                                color: gridBorderColor,
                                borderDash: [6],
                                borderDashOffset: [2],
                            }
                        }],
                        yAxes: [{
                            gridLines: {
                                color: gridBorderColor,
                                zeroLineColor: gridBorderColor,
                                borderDash: [6],
                                borderDashOffset: [2],
                            },
                            ticks: {
                                color: 'red',
                                beginAtZero: true,
                                padding: 10,
                                callback: function (a) {
                                    if (!(a % 10)) return a
                                }
                            }
                        }],
                    },
                    tooltips: {
                        enabled: false,
                        mode: "index",
                        intersect: false,
                        custom: function(tooltipModel) {
                            var tooltipContainer = $("#chart-tooltip");

                            if (!tooltipContainer.length) {
                                tooltipContainer = $('<div id="chart-tooltip" class="chartjs-tooltip chartjs-tooltip-top" role="tooltip"></div>');
                                $("body").append(tooltipContainer);
                            }

                            if (tooltipModel.opacity !== 0) {
                                if (tooltipModel.body) {
                                    var title = tooltipModel.title || [];
                                    var bodyLines = tooltipModel.body.map(function(bodyItem) {
                                        return bodyItem.lines;
                                    });
                                    var tooltipContent = "";

                                    tooltipContent += '<div class="arrow"></div>';

                                    title.forEach(function(titleItem) {
                                        tooltipContent += '<h3 class="chartjs-tooltip-header">' + titleItem + '</h3>';
                                    });

                                    bodyLines.forEach(function(body, index) {
                                        var indicator = '<span class="chartjs-tooltip-body-indicator"></span>';
                                        var alignment = 'justify-left';

                                        tooltipContent += '<div class="chartjs-tooltip-body flex items-center ' + alignment + '">' + indicator + body + '</div>';
                                    });

                                    tooltipContainer.html(tooltipContent);
                                }

                                var chartCanvas = $(this._chart.canvas);
                                var canvasOffsetTop = chartCanvas.offset().top;
                                var canvasOffsetLeft = chartCanvas.offset().left;
                                var containerWidth = tooltipContainer.outerWidth();
                                var containerHeight = tooltipContainer.outerHeight();
                                var tooltipY = canvasOffsetTop + tooltipModel.caretY - containerHeight - 16;
                                var tooltipX = canvasOffsetLeft + tooltipModel.caretX - containerWidth / 2;

                                tooltipContainer.css({
                                    top: tooltipY + "px",
                                    left: tooltipX + "px",
                                    display: "block"
                                });
                            } else {
                                tooltipContainer.css("display", "none");
                            }
                        },
                        callbacks: {
                            label: function(tooltipItem, data) {
                                var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || "";
                                var yLabel = tooltipItem.yLabel;
                                var tooltipLabel = "";

                                if (data.datasets.length > 1) {
                                    tooltipLabel += '<span class="chartjs-tooltip-body-label">' + datasetLabel + '</span>';
                                }

                                tooltipLabel += '<span class="chartjs-tooltip-body-value">' + yLabel + '</span>';

                                return tooltipLabel;
                            }
                        }
                    },
                    legend: {
                        display: false
                    },
                },
                data: {
                    labels: labels,
                    datasets: [{
                        borderColor: borderColor,
                        backgroundColor: 'transparent',
                        label: "Stats",
                        data: data
                    }]
                }
            });
        },
        updateChart(newData = null, newLabels = null) {
            if (newLabels !== null) {
                this.chart.data.labels = newLabels
            }
            if (newData !== null) {
                this.chart.data.datasets[0].data = newData
            }

            this.chart.update()
        },
    }
}

function overviewChart() {
    return {
        chart: null,
        chartEarnCache: {
            total: null,
            data: null,
            isLoading: true
        },
        chartUserCache: {
            total: null,
            data: null,
            isLoading: true
        },
        init() {
            const gridBorderColor = this.activeTheme === 'dark' ? "#2b2b2b" : "rgb(226 232 240)"
            const borderColor = "#255aef"

            let chartSelect = this.$refs.chart
            if (chartSelect === undefined) chartSelect = document.getElementById('chart')

            this.chart = new Chart(chartSelect, {
                type: "line",
                options: {
                    responsive: true,
                    scales: {
                        xAxes: [{
                            gridLines: {
                                display: true,
                                color: gridBorderColor,
                                borderDash: [6],
                                borderDashOffset: [2],
                            }
                        }],
                        yAxes: [{
                            gridLines: {
                                color: gridBorderColor,
                                zeroLineColor: gridBorderColor,
                                borderDash: [6],
                                borderDashOffset: [2],
                            },
                            ticks: {
                                color: 'red',
                                beginAtZero: true,
                                padding: 10,
                                callback: function (a) {
                                    if (!(a % 10)) return a
                                }
                            }
                        }],
                    },
                    tooltips: {
                        enabled: false,
                        mode: "index",
                        intersect: false,
                        custom: function(tooltipModel) {
                            var tooltipContainer = $("#chart-tooltip");

                            if (!tooltipContainer.length) {
                                tooltipContainer = $('<div id="chart-tooltip" class="chartjs-tooltip chartjs-tooltip-top" role="tooltip"></div>');
                                $("body").append(tooltipContainer);
                            }

                            if (tooltipModel.opacity !== 0) {
                                if (tooltipModel.body) {
                                    var title = tooltipModel.title || [];
                                    var bodyLines = tooltipModel.body.map(function(bodyItem) {
                                        return bodyItem.lines;
                                    });
                                    var tooltipContent = "";

                                    tooltipContent += '<div class="arrow"></div>';

                                    title.forEach(function(titleItem) {
                                        tooltipContent += '<h3 class="chartjs-tooltip-header">' + titleItem + '</h3>';
                                    });

                                    bodyLines.forEach(function(body, index) {
                                        var indicator = '<span class="chartjs-tooltip-body-indicator"></span>';
                                        var alignment = 'justify-left';

                                        tooltipContent += '<div class="chartjs-tooltip-body flex items-center ' + alignment + '">' + indicator + body + '</div>';
                                    });

                                    tooltipContainer.html(tooltipContent);
                                }

                                var chartCanvas = $(this._chart.canvas);
                                var canvasOffsetTop = chartCanvas.offset().top;
                                var canvasOffsetLeft = chartCanvas.offset().left;
                                var containerWidth = tooltipContainer.outerWidth();
                                var containerHeight = tooltipContainer.outerHeight();
                                var tooltipY = canvasOffsetTop + tooltipModel.caretY - containerHeight - 16;
                                var tooltipX = canvasOffsetLeft + tooltipModel.caretX - containerWidth / 2;

                                tooltipContainer.css({
                                    top: tooltipY + "px",
                                    left: tooltipX + "px",
                                    display: "block"
                                });
                            } else {
                                tooltipContainer.css("display", "none");
                            }
                        },
                        callbacks: {
                            label: function(tooltipItem, data) {
                                var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || "";
                                var yLabel = tooltipItem.yLabel;
                                var tooltipLabel = "";

                                if (data.datasets.length > 1) {
                                    tooltipLabel += '<span class="chartjs-tooltip-body-label">' + datasetLabel + '</span>';
                                }

                                tooltipLabel += '<span class="chartjs-tooltip-body-value">' + yLabel + '</span>';

                                return tooltipLabel;
                            }
                        }
                    },
                    legend: {
                        display: false
                    },
                },
                data: {
                    labels: [
                        lang.months.january,
                        lang.months.february,
                        lang.months.march,
                        lang.months.april,
                        lang.months.may,
                        lang.months.june,
                        lang.months.july,
                        lang.months.august,
                        lang.months.september,
                        lang.months.october,
                        lang.months.november,
                        lang.months.december,
                    ],
                    datasets: [{
                        borderColor: borderColor,
                        backgroundColor: 'transparent',
                        label: "Stats",
                        data: ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
                    }]
                }
            });

            this.fetchData('earn').then(data => {
                this.chartEarnCache.total = data.yearEarnedMoneyValue
                this.chartEarnCache.data = data.yearEarnedMoneyData

                this.updateData('earn');

                this.chartEarnCache.isLoading = false
            })
            this.fetchData('user').then(data => {
                this.chartUserCache.total = data.yearRegisteredUsersValue
                this.chartUserCache.data = data.yearRegisteredUsersData

                this.chartUserCache.isLoading = false
            })
        },
        updateChart(newData = null) {
            this.chart.data.datasets[0].data = newData
            this.chart.update()
        },
        updateData(action) {
            if (action === 'earn') this.updateChart(this.chartEarnCache.data)
            if (action === 'user') this.updateChart(this.chartUserCache.data)
        },
        fetchData(action = 'earn') {
            return axios.get('/dashboard/ajax/stats?target=chart&action=' + action)
                .then(response => response.data);
        }
    }
}

function cardData(action) {
    return {
        text: null,
        calculate: null,
        process: false,
        data: null,
        init() {
            axios.get('/dashboard/ajax/stats?target=card&action=' + action)
                .then(response => response.data)
                .then(data => {
                    this.data = data
                    this.process = true
                })
        },
        calculator(one, two) {
            if (one === undefined || two === undefined) return 0;
            return Math.floor(((100 * (one - two)) / (Math.max(1, two))))
        },
        badgeClass(calculate) {
            return (calculate > 0) ? 'badge-soft-success' : (calculate < 0) ? 'badge-soft-danger' : (calculate === 0) ? 'badge-soft-secondary' : '';
        }
    }
}

function $request(url, data = null, method = 'POST') {
    let csrfToken
    method = method.toUpperCase()

    if (method !== 'GET')
        csrfToken = document.querySelector('meta[name="csrf-token"]').content

    let requestOptions  = {
        url,
        method,
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': csrfToken,
        }
    }

    if (data !== null && method !== 'GET')
        requestOptions.data = JSON.stringify(data);

    return axios(requestOptions)
}

function $ajax(url, data = null, method = 'POST') {
    url = '/dashboard/ajax/' + url
    return $request(url, data, method)
}

function startApp() {
    const defaultTheme = window.matchMedia("(prefers-color-scheme: dark)") ? "dark" : "light";
    return {
        activeMenu: false,
        activeTheme: getCookie('theme') ?? defaultTheme,
        sideColorBlue: (getCookie('sidePanel') === 'true'),

        sideDetails: (getCookie('sideDetailsOpen') === 'true'),
        alwaysSideDetailsOpen: getCookie('always_SideDetailsOpen') === null ? true : (getCookie('always_SideDetailsOpen') === 'true'),
        sideTab: 'dashboard',
        modal: '',
        modalData: null,

        alert: {
            title: '',
            message: '',
            type: '',
            confirm: null,
            confirmText: '',
        },
        headerMenu: {
            title: '',
            icon: '',
            route: '',
            url: '',
            tab: '',
            module: '',
        },
        headerEdit: false,

        init() {
            this.switchTheme(this.activeTheme)

            const watchAndCreateCookie = (property, cookieName) => {
                this.$watch(property, (value) => {
                    createCookie(cookieName, value, 30)
                })
            }

            watchAndCreateCookie('activeTheme', 'theme')
            watchAndCreateCookie('sideColorBlue', 'sidePanel')
            watchAndCreateCookie('sideDetails', 'sideDetailsOpen')
            watchAndCreateCookie('alwaysSideDetailsOpen', 'always_SideDetailsOpen')

            document.querySelector('HTML').addEventListener("keydown", (event) => {
                const keyCode = event.keyCode || event.which

                if (keyCode === 27) this.modal = ''
            })
        },
        aside() {
            return {
                ['@click.outside'](event) {
                    this.closeSideDetails()

                    let btn = document.getElementById('activeMenuButton')
                    let element = event.target
                    let parentNodes = []
                    while (element.parentNode) {
                        parentNodes.push(element.parentNode);
                        element = element.parentNode;
                    }

                    const main = document.querySelector('main').classList
                    if (!parentNodes.includes(btn)) {
                        this.activeMenu = false
                        main.remove('after-blur')
                    }

                },
                ['x-bind:class']() {
                    return this.activeMenu ? 'active' : null
                }
            }
        },
        toggleActiveMenu() {
            this.activeMenu = !this.activeMenu
            this.alwaysSideDetailsOpen = window.innerWidth < 1024
            console.log(this.alwaysSideDetailsOpen)

            const main = document.querySelector('main').classList
            if (this.activeMenu) main.add('after-blur')
            else main.remove('after-blur')
        },

        toggleSideDetails(tab) {
            if (this.sideTab === tab) {
                this.sideDetails = !this.sideDetails
            } else {
                this.sideDetails = true
                this.sideTab = tab
            }
        },
        closeSideDetails() {
            if (!this.alwaysSideDetailsOpen) {
                this.sideDetails = false
            }
        },
        activeModal(modal, data = null) {
            this.modal = modal
            this.modalData = data
        },
        closeModal() {
            this.modal = ''
            this.modalData = null
        },
        openAlert(event) {
            this.modal = 'alert'
            this.alert.title = event.title
            this.alert.message = event.message
            this.alert.type = event.type
            this.alert.confirmClass = event.confirmClass ?? null
            this.alert.confirm = event.confirm ?? null
            this.alert.confirmText = event.confirmText ?? null
        },
        switchTheme(theme) {
            const html = document.querySelector('html').classList
            this.activeTheme = theme
            switch (theme) {
                case 'dark':
                    html.add('dark')
                    html.remove('dark-blue')
                    this.sideColorBlue = false
                    break
                case 'dark-blue':
                    html.add('dark')
                    html.add('dark-blue')
                    this.sideColorBlue = false
                    break
                case 'light':
                    html.remove('dark')
                    break
            }
        },
        toggleSideColor() {
            this.sideColorBlue = (this.activeTheme === 'light') ? !this.sideColorBlue : this.sideColorBlue
        },
        tooltip(text, placement = 'top') {
            return {
                ['x-tooltip.animation.shift-away-subtle.placement.' + placement]() {
                    return text
                }
            }
        },
        checkConsole() {
            const data = {
                serverIP: document.getElementById('ip')?.value,
                consoleID: document.getElementById('consoleID')?.value,
                consolePort: document.getElementById('consolePort')?.value,
                consolePassword: document.getElementById('consolePassword')?.value,
                consoleToken: document.getElementById('consoleToken')?.value,
            }
            this.$el.style.pointerEvents = 'none';
            this.$el.getElementsByTagName('svg')[0].style.display = 'inline-block';
            this.$el.getElementsByTagName('span')[0].innerHTML = lang.server_checking;

            $ajax('check/console', data)
                .then(response => response.data)
                .then(result => {
                    this.$el.style.pointerEvents = 'all';
                    this.$el.getElementsByTagName('svg')[0].style.display = 'none';
                    this.$el.getElementsByTagName('span')[0].innerHTML = lang.server_check;

                    if (result.status === false) {
                        return this.$dispatch('open-alert', {
                            type: 'danger',
                            title: lang.alert_title_error,
                            message: lang.server_connection_error + ' ' + result.message
                        })
                    }
                    
                    if (data.consoleID == 4) {
                        return this.$dispatch('open-alert', {
                            type: 'info',
                            title: lang.alert_title_check_leaderos_connect,
                            message: lang.alert_message_check_leaderos_connect
                        })
                    }

                    return this.$dispatch('open-alert', {
                        type: 'success',
                        title: lang.alert_title_success,
                        message: lang.server_connection_success
                    })
                })
        },
        checkSqlConnection() {
            const data = {
                mysqlServer: document.getElementById('mysqlServer').value,
                mysqlPort: document.getElementById('mysqlPort').value,
                mysqlUsername: document.getElementById('mysqlUsername').value,
                mysqlPassword: document.getElementById('mysqlPassword').value,
                mysqlDatabase: document.getElementById('mysqlDatabase').value
            }
            this.$el.style.pointerEvents = 'none';
            this.$el.getElementsByTagName('svg')[0].style.display = 'inline-block';
            this.$el.getElementsByTagName('span')[0].innerHTML = lang.db_checking;
            $ajax('check/mysql', data)
                .then(response => response.data)
                .then(result => {
                    this.$el.style.pointerEvents = 'all';
                    this.$el.getElementsByTagName('svg')[0].style.display = 'none';
                    this.$el.getElementsByTagName('span')[0].innerHTML = lang.db_check;

                    if (result.status === false) {
                        return this.$dispatch('open-alert', {
                            type: 'danger',
                            title: lang.alert_title_error,
                            message: lang.db_connection_error + ' ' + result.message
                        })
                    }

                    return this.$dispatch('open-alert', {
                        type: 'success',
                        title: lang.alert_title_success,
                        message: lang.db_connection_success
                    })
                })
        },
        checkSmtp() {
            const data = {
                smtpServer: document.getElementById('inputSMTPServer').value,
                smtpPort: document.getElementById('inputSMTPPort').value,
                smtpSecure: document.getElementById('selectSMTPSecure').value,
                smtpSenderEmail: document.getElementById('inputSMTPSenderEmail').value,
                smtpUsername: document.getElementById('inputSMTPUsername').value,
                smtpPassword: document.getElementById('inputSMTPPassword').value
            }
            this.$el.style.pointerEvents = 'none';
            this.$el.getElementsByTagName('svg')[0].style.display = 'inline-block';
            this.$el.getElementsByTagName('span')[0].innerHTML = lang.smtp_btn_checking;
            $ajax('check/smtp', data)
                .then(response => response.data)
                .then(result => {
                    this.$el.style.pointerEvents = 'all';
                    this.$el.getElementsByTagName('svg')[0].style.display = 'none';
                    this.$el.getElementsByTagName('span')[0].innerHTML = lang.smtp_btn_check;

                    if (result.status === false) {
                        return this.$dispatch('open-alert', {
                            type: 'danger',
                            title: lang.alert_title_error,
                            message: result.message
                        })
                    }

                    return this.$dispatch('open-alert', {
                        type: 'success',
                        title: lang.alert_title_success,
                        message: lang.smtp_connection_success
                    })
                })
        },
        checkWebhook() {
            const data = {
                url: document.getElementById('url').value,
                event: document.querySelector('input[name="event"]:checked').value,
                botName: document.getElementById('botName').value,
                botAvatar: document.getElementById('botAvatar').value,
                data: editor.getValue()
            }
            this.$el.style.pointerEvents = 'none';
            this.$el.getElementsByTagName('svg')[0].style.display = 'inline-block';
            this.$el.getElementsByTagName('span')[0].innerHTML = lang.webhook_test_message_sending;
            console.log(data);
            $ajax('check/webhook', data)
                .then(response => response.data)
                .then(result => {
                    this.$el.style.pointerEvents = 'all';
                    this.$el.getElementsByTagName('svg')[0].style.display = 'none';
                    this.$el.getElementsByTagName('span')[0].innerHTML = lang.webhook_test_message_send;

                    if (result.status === false) {
                        return this.$dispatch('open-alert', {
                            type: 'danger',
                            title: lang.alert_title_error,
                            message: lang.alert_message_webhook_error
                        })
                    }

                    return this.$dispatch('open-alert', {
                        type: 'success',
                        title: lang.alert_title_success,
                        message: lang.alert_message_webhook_success
                    })
                })
        },
        syncForum() {
            const data = {
                selectParentID: document.getElementById('selectParentID').value
            }

            $ajax('forum/category', data).then(response => response.data).then(result => {
                document.querySelector('#forumPermissions input[type=hidden]').value = 0
                document.querySelector('#forumPermissions input[type=checkbox]').checked - false

                result = JSON.parse(result);
                for (let i = 0; i < result.length; i++) {
                    let roleID = result[i].roleID;
                    let permissionID = result[i].permissionID;

                    let permissionInput = document.querySelector(`#forumPermissions input[name=permission_${roleID}_${permissionID}]`);
                    if (permissionInput) {
                        permissionInput.value = 1;
                    }

                    let checkbox = document.querySelector(`#forumPermissions #checkbox-${roleID}_${permissionID}`);
                    if (checkbox) {
                        checkbox.checked = true;
                    }
                }

            })
        },
        async toggleModule(id) {
            return await $request('/dashboard/modules/toggle/' + id)
                .then(response => response.data)
                .then(result => {
                    if (result.status === 'success') {
                        this.$dispatch('notice', {
                            type: 'success',
                            title: lang.alert_title_success,
                            text: result.message
                        })
                    }
                    if (result.status === 'error') {
                        this.$dispatch('notice', {
                            type: 'error',
                            title: lang.alert_title_error,
                            text: result.message
                        })
                    }
                });
        },
        async toggleAccountLinkingProvider(id) {
            return await $request('/dashboard/settings/account-linking/toggle-provider/' + id)
              .then(response => response.data)
              .then(result => {
                  if (result.status === 'success') {
                      this.$dispatch('notice', {
                          type: 'success',
                          title: lang.alert_title_success,
                          text: result.message
                      })
                  }
                  if (result.status === 'error') {
                      this.$dispatch('notice', {
                          type: 'error',
                          title: lang.alert_title_error,
                          text: result.message
                      })
                  }
              });
        },
        toggleApiStatus() {
            return $request('/dashboard/settings/api/toggle')
                .then(response => response.data)
                .then(result => {
                    if (result.status === 'success') {
                        this.$dispatch('notice', {
                            type: 'success',
                            title: lang.alert_title_success,
                            text: result.message
                        })
                    }
                });
        },
        generateWithAi(prompt, event = null) {
            if (prompt === undefined || prompt === null || prompt.trim() === '') {
                return;
            }
            if (event !== null && event.shiftKey) return;
            if (event !== null) event.preventDefault();

            this.isAiGenerating = true;
            $request('/dashboard/ai/generate-with-ai', {
                prompt: prompt,
                type: this.modalData.type,
            })
                .then(response => response.data)
                .then(result => {
                    if (result.status) {
                        if (ckeditor !== undefined && ckeditor?.sourceElement === document.querySelector(this.modalData.target)) {
                            ckeditor.setData(result.content);
                        } else {
                            const targetElement = document.querySelector(this.modalData.target);
                            if (targetElement) {
                                targetElement.value = result.content;
                            } else {
                                console.error('Target element not found:', this.modalData.target);
                            }
                        }
                        this.closeModal();
                    } else {
                        this.$dispatch('open-alert', {
                            type: 'error',
                            title: lang.alert_title_error,
                            message: result.error
                        });
                    }
                })
                .catch(error => {
                    console.error('Error generating content with AI:', error);
                })
                .finally(() => {
                    this.isAiGenerating = false;
                });
        }
    }
}

function noticesHandler() {
    return {
        notices: [],
        visible: [],
        add(notice) {
            notice.id = Date.now()
            this.notices.push(notice)
            this.fire(notice.id)
            this.$nextTick(() => {
                feather.replace();
            });
        },
        fire(id) {
            this.visible.push(this.notices.find(notice => notice.id == id))
            const timeShown = 2000 * this.visible.length
            setTimeout(() => {
                this.remove(id)
            }, timeShown)
        },
        remove(id) {
            const notice = this.visible.find(notice => notice.id == id)
            const index = this.visible.indexOf(notice)
            this.visible.splice(index, 1)
        },
    }
}

function tab(defaultTab = '') {
    return {
        activeTab: defaultTab,
        toggleTab(tab) {
            this.activeTab = this.activeTab === tab ? '' : tab
        },
        openTab(tab) {
            this.activeTab = tab
        }
    }
}

function table() {
    return {
        selects: [],
        init() {
            this.$watch('selects', (selects) => {
                let values = this.getValues()
                this.$refs.table.rows[0].querySelector('input[type=checkbox]').checked = arraysAreEqual(selects, values)
            })
        },
        getValues() {
            let values = []
            Array.from(this.$refs.table.rows).map((row) => {
                const value = row.children[0].querySelector('input[type=checkbox]').value
                if (value !== 'on')
                    values.push(value)
            })
            return values
        },
        toggle: {
            ['@click']() {
                let values = this.getValues()
                if (arraysAreEqual(this.selects, values)) {
                    this.selects = []
                } else {
                    this.selects = values
                }
            }
        },
        removeRequest: {
            ['@click']() {
                if (this.selects.length === 0) {
                    return this.$dispatch('open-alert', {
                        type: 'warning',
                        title: lang.delete_selected_no_selected_title,
                        message: lang.delete_selected_no_selected_message
                    })
                }

                this.$dispatch('open-alert', {
                    type: 'delete',
                    title: lang.alert_title_warning,
                    message: lang.delete_selected_confirm_message,
                    confirm: 'confirm-remove',
                    confirmText: lang.alert_btn_delete
                })
            },
            ['@confirm-remove.window'](event) {
                $request('/dashboard/support/tickets/delete-selected', {
                    selectedItems: this.selects
                }, 'DELETE').then(response => {
                    if (response.data.status === 'success') {
                        this.$dispatch('open-alert', {
                            type: 'success',
                            title: lang.alert_title_success,
                            message: lang.delete_selected_success,
                            confirm: function()  {
                                location.reload()
                            }
                        })
                        this.selects = []
                    }
                })
            }
        }
    }
}

function minecraftIconPicker(selected = null, disableDefault = false) {
    return {
        select2: null,
        init() {
            this.$nextTick(() => {
                this.select2 = $(this.$el).select2({
                    placeholder: lang.loading
                })
                axios.get('/dashboard/ajax/minecraft-items?disableDefault=' + disableDefault)
                    .then(response => response.data)
                    .then(data => {
                        const select2Options = {
                            templateResult: this.formatState,
                            data: $.map(data, function(obj) {
                                return {
                                    id: obj.item,
                                    text: obj.name,
                                    icon: obj.icon
                                };
                            })
                        };

                        this.select2.empty(); // Clear existing options
                        this.select2.select2(select2Options); // Initialize select2

                        if (selected === null && !disableDefault) {
                            selected = 'default';
                        }

                        if (selected !== null)
                            this.select2.val(selected).trigger('change');
                    });

            })
        },
        formatState: (state) => {
            let $state = state.text;

            if (state.icon) {
                var baseUrl = "/apps/main/public/images/items";
                $state = $('<span style="display: flex; gap: 6px;"><img src="' + baseUrl + '/' + state.id + '.png" style="margin-right: 6px; max-width: 32px; max-height: 32px;" /> ' + state.text + '</span>');
            }

            return $state;
        }
    }
}

function multiSelect(defaultValue = null, list = null) {
    return {
        select2: null,
        selected: null,
        onChange(func = () => {}) {
            this.$nextTick(() => {
                this.$watch('selected', (value) => {
                    func(value)
                });
            });
        },
        init() {
            this.$nextTick(async () => {
                const placeholder = this.$el.getAttribute('placeholder')
                this.select2 = $(this.$el).select2({
                    placeholder: lang.loading
                })
                
                const select2Options = {
                    placeholder,
                    templateResult: this.formatState,
                    data: this.parseData(list)
                };
                
                this.select2.empty(); // Clear existing options
                this.select2.select2(select2Options); // Initialize select2
                
                this.select2.on('select2:select', event => {
                    this.selected = this.select2.val()
                })
                this.select2.on('select2:unselect', event => {
                    this.selected = this.select2.val()
                })
                
                this.$watch("selected", value => {
                    this.select2.val(value).trigger("change")
                })
                
                if (defaultValue !== null && defaultValue !== '') {
                    this.selected = defaultValue;
                } else {
                    this.select2.val('').trigger('change');
                }
            })
        },
        parseData(data) {
            let result = [];
            data.map((item) => {
                result.push({
                    id: item.id,
                    text: item.text,
                });
            });
            return result;
        },
        formatState: (state) => {
            return $('<span>' + state.text + '</span>');
        }
    }
}

function selectProduct(defaultValue = null, list = null, isMultiple = false) {
    return {
        select2: null,
        selected: null,
        isMultiple: isMultiple,
        onChange(func = () => {}) {
            this.$nextTick(() => {
                this.$watch('selected', (value) => {
                    func(value)
                });
            });
        },
        init() {
            this.$nextTick(async () => {
                const placeholder = this.$el.getAttribute('placeholder')
                this.select2 = $(this.$el).select2({
                    placeholder: lang.loading
                })

                if (list === null) {
                    list = await axios.get('/dashboard/ajax/tore/products/tree');
                    list = list.data.categories;
                }

                const select2Options = {
                    placeholder,
                    templateResult: this.formatState,
                    data: this.selectProductTree(list)
                };

                this.select2.empty(); // Clear existing options
                this.select2.select2(select2Options); // Initialize select2

                this.select2.on('select2:select', event => {
                    if (this.isMultiple) {
                        this.selected = this.select2.val()
                    } else {
                        this.selected = event.target.value
                    }
                })

                this.$watch("selected", value => {
                    this.select2.val(value).trigger("change")
                })

                if (defaultValue !== null && defaultValue !== '') {
                    this.selected = defaultValue;
                } else {
                    this.select2.val('').trigger('change');
                }
            })
        },
        selectProductTree(tree, level = 0) {
            let result = [];
            tree.map((item) => {
                const isCategory = item.subcategories !== undefined || item.products !== undefined;
                result.push({
                    id: isCategory ? ("C-" + item.id) : item.id,
                    text: item.name,
                    level: level,
                    isCategory: isCategory,
                    isExpandable: isCategory && ((item.subcategories !== undefined && item.subcategories.length > 0) || (item.products !== undefined && item.products.length > 0)),
                    disabled: isCategory
                });
                if (item.products !== undefined) {
                    level++;
                    result = result.concat(this.selectProductTree(item.products, level))
                    level--;
                }
                if (item.subcategories !== undefined) {
                    level++;
                    result = result.concat(this.selectProductTree(item.subcategories, level))
                    level--;
                }
            });
            return result;
        },
        formatState: (state) => {
            let $state;

            if (state.isCategory) {
                $state = $(
                  '<span class="select2__selectProduct_disabled" style="padding-left: ' + state.level * 15 + 'px">' +
                    state.text +
                  '</span>'
                );
            } else {
                $state = $(
                  '<span style="padding-left: ' + state.level * 15 + 'px">' +
                    state.text +
                  '</span>'
                );
            }

            return $state;
        }
    }
}

function selectCategory(defaultValue = null, list = null) {
    return {
        select2: null,
        selected: null,
        onChange(func = () => {}) {
            this.$nextTick(() => {
                this.$watch('selected', (value) => {
                    func(value)
                });
            });
        },
        init() {
            this.$nextTick(async () => {
                const placeholder = this.$el.getAttribute('placeholder')
                this.select2 = $(this.$el).select2({
                    placeholder: lang.loading
                })

                if (list === null) {
                    list = await axios.get('/dashboard/ajax/store/categories');
                    list = list.data;
                }

                const select2Options = {
                    placeholder,
                    templateResult: this.formatState,
                    data: this.selectCategoryTree(list),
                };

                this.select2.empty(); // Clear existing options
                this.select2.select2(select2Options); // Initialize select2

                this.select2.on('select2:select', event => {
                    this.selected = event.target.value
                })

                this.$watch("selected", value => {
                    this.select2.val(value).trigger("change")
                })

                if (defaultValue !== null && defaultValue !== '') {
                    this.selected = defaultValue;
                } else {
                    this.select2.val('').trigger('change');
                }
            })
        },
        selectCategoryTree(tree, level = 0) {
            let result = [];
            tree.map((item) => {
                result.push({
                    id: item.id,
                    text: item.name,
                    level: level,
                    isExpandable: item.subcategories !== undefined && item.subcategories !== null && item.subcategories.length > 0,
                });
                if (item.subcategories !== undefined) {
                    level++;
                    result = result.concat(this.selectCategoryTree(item.subcategories, level))
                    level--;
                }
            });
            return result;
        },
        formatState: (state) => {
            const $state = $(
              '<span style="padding-left: ' + state.level * 15 + 'px">' +
                state.text +
              '</span>'
            );
            
            return $state;
        }
    }
}

function selectSearchUser(defaultValue = null) {
    return {
        select2: null,
        selected: null,
        currentPage: 1, // For tracking pagination
        isLoadingForDefault: false,
        onChange(callback = () => {}) {
            this.$nextTick(() => {
                this.$watch('selected', (value) => {
                    callback(value);
                });
            });
        },
        async init() {
            this.$nextTick(async () => {
                const placeholder = this.$el.getAttribute('placeholder');
                
                // Initialize Select2 with AJAX and infinite scroll support
                this.select2 = $(this.$el).select2({
                    placeholder: placeholder || 'Search User',
                    minimumInputLength: 3,
                    ajax: {
                        url: '/dashboard/ajax/search-user',
                        dataType: 'json',
                        delay: 250,
                        data: (params) => {
                            // Send pagination parameters along with the search term
                            return {
                                query: params.term || '', // The search term
                                page: params.page || 1,   // Current page
                            };
                        },
                        processResults: (data, params) => {
                            // Update page number for infinite scroll
                            params.page = params.page || 1;
                            
                            return {
                                results: data.users.map(user => ({
                                    id: user.id,
                                    text: user.displayName,
                                    avatar: user.avatar,
                                    username: user.username
                                })),
                                pagination: {
                                    more: data.hasMore // `true` if more results are available
                                }
                            };
                        },
                        cache: true
                    },
                    templateResult: this.formatState,
                    templateSelection: this.formatSelection
                });
                
                // If defaultValue is provided, fetch and set the user
                if (defaultValue !== null && defaultValue !== '') {
                    this.isLoadingForDefault = true;
                    const response = await axios.get(`/dashboard/ajax/search-user?id=${defaultValue}`);
                    const user = response.data;
                    
                    if (user) {
                        const option = new Option(user.displayName, user.id, true, true);
                        option.dataset.avatar = user.avatar;
                        option.dataset.username = user.username;
                        
                        // Add the user to Select2 and set it as selected
                        this.select2.append(option).trigger('change');
                        this.selected = user.id;
                        this.isLoadingForDefault = false;
                    }
                }
                
                this.select2.on('select2:select', (event) => {
                    this.selected = event.params.data.id;
                });
                
                this.$watch('selected', (value) => {
                    this.select2.val(value).trigger('change');
                });
            });
        },
        formatState: (state) => {
            if (!state.id) {
                return state.text;
            }
            const $state = $(`
                <div class="flex items-center">
                    <img src="${state.avatar || ''}" alt="Avatar" class="w-8 h-8 rounded-md mr-2">
                    <div>
                        <div class="font-medium">${state.text}</div>
                        <div class="text-xs text-gray-500">@${state.username || ''}</div>
                    </div>
                </div>
            `);
            return $state;
        },
        formatSelection: (state) => {
            if (!state.id) {
                return state.text;
            }
            return $(`
                <div class="flex items-center">
                    <img src="${state.avatar || state.element.dataset.avatar}" alt="Avatar" class="w-5 h-5 rounded-md mr-2">
                    <span>${state.text}</span>
                    <span class="text-xs ml-1">(@${state.username || state.element.dataset.username})</span>
                </div>
            `);
        }
    };
}


function textEditor() {
    return {
        editor: null,
        init() {
            this.editor = this.$refs.textEditor
            if (this.editor) {
                // Next tick
                this.$nextTick(() => {
                    const placeholder = this.editor.placeholder
                    const csrfToken = document.querySelector('meta[name="csrf-token"]').content
                    ClassicEditor
                      .create(this.editor, {
                          language: language,
                          placeholder: placeholder,
                          htmlSupport: {
                              allow: [
                                  {
                                      name: /.*/,
                                      attributes: true,
                                      classes: true,
                                      styles: true
                                  }
                              ]
                          },
                          mediaEmbed: {
                              previewsInData:true
                          },
                          simpleUpload: {
                              // The URL that the images are uploaded to.
                              uploadUrl: '/dashboard/ajax/editor/upload',
                              
                              // Enable the XMLHttpRequest.withCredentials property.
                              withCredentials: true,
                              
                              // Headers sent along with the XMLHttpRequest to the upload server.
                              headers: {
                                  'X-CSRF-TOKEN': csrfToken,
                              }
                          }
                      })
                      .then(newEditor => {
                          ckeditor = newEditor;
                      })
                      .catch(error => {
                          console.error(error);
                      });
                });
            }
        }
    }
}

function tagInput(tags = []) {
    return {
        tags: tags,
        warning: false,
        /* bind click */
        tagInput: {
            ['x-ref']: 'tagInput',
            ['x-on:keydown.enter.prevent']() {
                this.add();
            }
        },
        add() {
            let tag = this.$refs.tagInput.value.trim()
            if (!this.tags.includes(tag) && tag) {
                if (tag.length >= 3 && tag.length <= 60) this.tags.push(tag)
                else {
                    this.warning = true
                    setTimeout(() => {
                        this.warning = false
                    }, 3000)
                }
            }

            this.$refs.tagInput.value = ''
        },
        deleteAll() {
            if (this.tags.length > 4) this.tags = []
        }
    }
}

function image() {
    return {
        imageUploaded: false,
        imagePreview: null,
        imageInput: {
            ['@change']() {
                this.imageUploaded = this.$event.target.files.length > 0

                if (this.imageUploaded) {
                    const file = this.$event.target.files[0]
                    const reader = new FileReader()

                    reader.onload = (e) => {
                        this.imagePreview = e.target.result
                    }

                    reader.readAsDataURL(file)
                } else this.imagePreview = null
            }
        },
        imageContainer: {
            [':class']() {
                return this.imageUploaded ? 'uploaded' : ''
            }
        }
    }
}

function fileSelect() {
    return {
        file: null,
        fileInput: {
            ['@change']() {
                if (this.$event.target.files.length === 0)
                    return;

                this.file = Object.values(this.$event.target.files)
            }
        },
        textTitle(text = 'Choose file...') {
            return {
                ['x-text']() {
                    return this.file ? this.file.map(file => file.name).join(', ') : text
                }
            }
        }
    }
}

function inputArray(defaultTemplate = {}, values = null) {
    return {
        inputs: [],
        onDelete: () => {},
        init() {
            if (values !== null && values.length > 0) {
                values.map(value => {
                    this.addInput(value);
                });
            } else {
                this.addInput();
            }
            this.$nextTick(() => {
                feather.replace();
            });
        },
        deleteInput(index) {
            if (this.inputs.length > 1) {
                console.log(index);
                this.inputs.splice(index, 1)

                this.onDelete(index);
            }
            this.$nextTick(() => {
                feather.replace();
            });
        },
        addInput(value = defaultTemplate) {
            this.inputs.push({...value})
            this.$nextTick(() => {
                feather.replace();
            });
        }
    }
}

function header(elements = []) {
    return {
        showHeaderMenu: false,
        defaultHeaderMenuModel: {
            id: "",
            title: "",
            icon: "fas fa-link",
            route: "custom",
            url: "",
            tab: "0",
            module: "",
        },
        headerMenuModel: {},
        editingElement: {},
        elements: elements,
        init() {
            console.log(this.elements);
            this.headerMenuModel = {...this.defaultHeaderMenuModel};
            const nestableContainer = $('#nestable-header-menu')
            this.$nextTick(() => {
                const options = {
                    maxDepth: 2,
                    callback: () => {
                        this.changeSave()
                    }
                }
                nestableContainer.nestable(options)
            });
            document.querySelector('HTML').addEventListener("keydown", (event) => {
                const keyCode = event.keyCode || event.which

                if (keyCode === 27 && this.showHeaderMenu !== false) this.showHeaderMenu = false;
            })
        },
        updateRequest(data = null) {
            if (data === null) data = this.elements;
            if (!Array.isArray(data)) return;

            $request('/dashboard/appearance/header/', {
                json: JSON.stringify(data)
            }, 'PATCH')
                .then(response => response.data)
                .then(response => {
                    if (response.status) {
                        this.$dispatch('notice', {
                            type: 'success',
                            title: lang.alert_title_success,
                            text: response.message
                        })
                    }
                    else {
                        this.$dispatch('notice', {
                            type: 'error',
                            title: lang.alert_title_error,
                            text: ""
                        })
                    }
                });
        },
        changeSave() {
            const before = this.elements;
            const nestableContainer = $('#nestable-header-menu');
            const current = nestableContainer.nestable("serialize");

            if (JSON.stringify(before) !== JSON.stringify(current) && Array.isArray(current)) {
                this.updateRequest(current);
            }
        },
        hideHeaderMenu() {
            this.editingElement = {};
            this.headerMenuModel = {...this.defaultHeaderMenuModel};

            this.showHeaderMenu = false;
        },
        showAddElementMenu() {
            this.headerMenuModel = {...this.defaultHeaderMenuModel};
            this.showHeaderMenu = 'add';
        },
        showEditElementMenu(element) {
            this.headerMenuModel = {
                title: element.title,
                icon: element.icon,
                route: element.route,
                url: element.url,
                tab: element.tab,
                module: element.module,
            };
            this.editingElement = element;
            this.showHeaderMenu = 'edit';
            
            // Fix route changes sync
            this.$nextTick(() => {
               this.headerMenuModel.title = element.title;
                this.headerMenuModel.icon = element.icon;
                this.headerMenuModel.url = element.url;
                this.headerMenuModel.tab = element.tab;
                this.headerMenuModel.module = element.module;
            });
        },
        addElement() {
            this.headerMenuModel.id = md5(new Date().getTime());
            this.elements.push({...this.headerMenuModel});

            this.hideHeaderMenu();
            this.updateRequest();
        },
        updateElement(element) {
            element.title = this.headerMenuModel.title;
            element.icon = this.headerMenuModel.icon;
            element.route = this.headerMenuModel.route;
            element.url = this.headerMenuModel.url;
            element.tab = this.headerMenuModel.tab;
            element.module = this.headerMenuModel.module;

            this.hideHeaderMenu();
            this.updateRequest();
        },
        removeElement(index, child = -1) {
            if (child !== -1) {
                this.elements[index].children.splice(child, 1);
            }
            else {
                if (this.elements[index].children && Array.isArray(this.elements[index].children)) {
                    this.elements[index].children.map(childItem => {
                        this.elements.push({...childItem});
                    });
                }
                this.elements.splice(index, 1);
            }

            this.$dispatch('notice', {
                type: 'success',
                title: lang.alert_title_success,
                text: lang.changes_saved
            })

            this.updateRequest();
        },
        handleChangeRoute(type) {
            const types = {
                'custom': {
                    title: '',
                    icon: 'fas fa-link',
                    url: '',
                    module: '',
                },
                'home': {
                    title: lang.routeTypes.home,
                    icon: 'fas fa-home',
                    url: '/',
                    module: '',
                },
                'store': {
                    title: lang.routeTypes.store,
                    icon: 'fas fa-shopping-cart',
                    url: '/store',
                    module: 'store',
                },
                'games': {
                    title: lang.routeTypes.games,
                    icon: 'fas fa-gamepad',
                    url: '/games',
                    module: 'games',
                },
                'lottery': {
                    title: lang.routeTypes.lottery,
                    icon: 'fas fa-chart-pie',
                    url: '/fortune-wheel',
                    module: 'lottery',
                },
                'credits': {
                    title: lang.routeTypes.buyCredits,
                    icon: 'fas fa-coins',
                    url: '/credits/charge',
                    module: 'credit',
                },
                'send-credits': {
                    title: lang.routeTypes.sendCredits,
                    icon: 'fas fa-coins',
                    url: '/credits/send',
                    module: 'credit',
                },
                'leaderboards': {
                    title: lang.routeTypes.leaderboards,
                    icon: 'fas fa-trophy',
                    url: '/leaderboards'
                },
                'support': {
                    title: lang.routeTypes.support,
                    icon: 'fas fa-life-ring',
                    url: '/support/tickets'
                },
                'chest': {
                    title: lang.routeTypes.chest,
                    icon: 'fas fa-archive',
                    url: '/chest',
                    module: 'chest',
                },
                'download': {
                    title: lang.routeTypes.download,
                    icon: 'fas fa-download',
                    url: '/download',
                    module: 'download',
                },
                'help': {
                    title: lang.routeTypes.help,
                    icon: 'fas fa-question-circle',
                    url: '/help',
                    module: 'help',
                },
                'bazaar': {
                    title: lang.routeTypes.bazaar,
                    icon: 'fas fa-store',
                    url: '/bazaar',
                    module: 'bazaar',
                },
                'gaming-night': {
                    title: lang.routeTypes.gamingNight,
                    icon: 'fas fa-moon',
                    url: '/gaming-night',
                    module: 'gaming_night',
                },
                'forum': {
                    title: lang.routeTypes.forum,
                    icon: 'fas fa-comment',
                    url: '/forum',
                    module: 'forum',
                },
                'staff': {
                    title: lang.routeTypes.staff,
                    icon: 'fas fa-crown',
                    url: '/staff',
                    module: 'staff',
                },
                'vote': {
                    title: lang.routeTypes.vote,
                    icon: 'fas fa-poll',
                    url: '/vote',
                    module: 'vote',
                },
                'punishments': {
                    title: lang.routeTypes.punishments,
                    icon: 'fas fa-ban',
                    url: '/punishments',
                    module: 'punishments',
                },
                'suggestions': {
                    title: lang.routeTypes.suggestions,
                    icon: 'fas fa-thumbs-up',
                    url: '/suggestions',
                    module: 'suggestions',
                },
                'changelog': {
                    title: lang.routeTypes.changelog,
                    icon: 'fas fa-check',
                    url: '/changelog',
                    module: 'changelog',
                }
            }
            this.headerMenuModel.title = types[type].title;
            this.headerMenuModel.icon = types[type].icon;
            this.headerMenuModel.url = types[type].url;
            this.headerMenuModel.route = type;
            this.headerMenuModel.tab = '0';
            this.headerMenuModel.module = types[type].module;
        },
    };
}

function footer(elements = []) {
    return {
        showFooterMenu: false,
        defaultFooterMenuModel: {
            id: "",
            title: "",
            icon: "fas fa-link",
            route: "custom",
            url: "",
            tab: "0",
            module: "",
        },
        footerMenuModel: {},
        editingElement: {},
        elements: elements,
        init() {
            console.log(this.elements);
            this.footerMenuModel = {...this.defaultFooterMenuModel};
            const nestableContainer = $('#nestable-footer-menu')
            this.$nextTick(() => {
                const options = {
                    maxDepth: 2,
                    callback: () => {
                        this.changeSave()
                    }
                }
                nestableContainer.nestable(options)
            });
            document.querySelector('HTML').addEventListener("keydown", (event) => {
                const keyCode = event.keyCode || event.which
                
                if (keyCode === 27 && this.showFooterMenu !== false) this.showFooterMenu = false;
            })
        },
        updateRequest(data = null) {
            if (data === null) data = this.elements;
            if (!Array.isArray(data)) return;
            
            $request('/dashboard/appearance/footer/', {
                json: JSON.stringify(data)
            }, 'PATCH')
              .then(response => response.data)
              .then(response => {
                  if (response.status) {
                      this.$dispatch('notice', {
                          type: 'success',
                          title: lang.alert_title_success,
                          text: response.message
                      })
                  }
                  else {
                      this.$dispatch('notice', {
                          type: 'error',
                          title: lang.alert_title_error,
                          text: ""
                      })
                  }
              });
        },
        changeSave() {
            const before = this.elements;
            const nestableContainer = $('#nestable-footer-menu');
            const current = nestableContainer.nestable("serialize");
            
            if (JSON.stringify(before) !== JSON.stringify(current) && Array.isArray(current)) {
                this.updateRequest(current);
            }
        },
        hideFooterMenu() {
            this.editingElement = {};
            this.footerMenuModel = {...this.defaultFooterMenuModel};
            
            this.showFooterMenu = false;
        },
        showAddElementMenu() {
            this.footerMenuModel = {...this.defaultFooterMenuModel};
            this.showFooterMenu = 'add';
        },
        showEditElementMenu(element) {
            this.footerMenuModel = {
                title: element.title,
                icon: element.icon,
                route: element.route,
                url: element.url,
                tab: element.tab,
                module: element.module,
            };
            this.editingElement = element;
            this.showFooterMenu = 'edit';
            
            // Fix route changes sync
            this.$nextTick(() => {
                this.footerMenuModel.title = element.title;
                this.footerMenuModel.icon = element.icon;
                this.footerMenuModel.url = element.url;
                this.footerMenuModel.tab = element.tab;
                this.footerMenuModel.module = element.module;
            });
        },
        addElement() {
            this.footerMenuModel.id = md5(new Date().getTime());
            this.elements.push({...this.footerMenuModel});
            
            this.hideFooterMenu();
            this.updateRequest();
        },
        updateElement(element) {
            element.title = this.footerMenuModel.title;
            element.icon = this.footerMenuModel.icon;
            element.route = this.footerMenuModel.route;
            element.url = this.footerMenuModel.url;
            element.tab = this.footerMenuModel.tab;
            element.module = this.footerMenuModel.module;
            
            this.hideFooterMenu();
            this.updateRequest();
        },
        removeElement(index, child = -1) {
            if (child !== -1) {
                this.elements[index].children.splice(child, 1);
            }
            else {
                if (this.elements[index].children && Array.isArray(this.elements[index].children)) {
                    this.elements[index].children.map(childItem => {
                        this.elements.push({...childItem});
                    });
                }
                this.elements.splice(index, 1);
            }
            
            this.$dispatch('notice', {
                type: 'success',
                title: lang.alert_title_success,
                text: lang.changes_saved
            })
            
            this.updateRequest();
        },
        handleChangeRoute(type) {
            const types = {
                'custom': {
                    title: '',
                    icon: 'fas fa-link',
                    url: '',
                    module: '',
                },
                'block': {
                    title: '',
                    icon: '',
                    url: '',
                    module: '',
                },
                'home': {
                    title: lang.routeTypes.home,
                    icon: 'fas fa-home',
                    url: '/',
                    module: '',
                },
                'store': {
                    title: lang.routeTypes.store,
                    icon: 'fas fa-shopping-cart',
                    url: '/store',
                    module: 'store',
                },
                'games': {
                    title: lang.routeTypes.games,
                    icon: 'fas fa-gamepad',
                    url: '/games',
                    module: 'games',
                },
                'lottery': {
                    title: lang.routeTypes.lottery,
                    icon: 'fas fa-chart-pie',
                    url: '/fortune-wheel',
                    module: 'lottery',
                },
                'credits': {
                    title: lang.routeTypes.buyCredits,
                    icon: 'fas fa-coins',
                    url: '/credits/charge',
                    module: 'credit',
                },
                'send-credits': {
                    title: lang.routeTypes.sendCredits,
                    icon: 'fas fa-coins',
                    url: '/credits/send',
                    module: 'credit',
                },
                'leaderboards': {
                    title: lang.routeTypes.leaderboards,
                    icon: 'fas fa-trophy',
                    url: '/leaderboards'
                },
                'support': {
                    title: lang.routeTypes.support,
                    icon: 'fas fa-life-ring',
                    url: '/support/tickets'
                },
                'chest': {
                    title: lang.routeTypes.chest,
                    icon: 'fas fa-archive',
                    url: '/chest',
                    module: 'chest',
                },
                'download': {
                    title: lang.routeTypes.download,
                    icon: 'fas fa-download',
                    url: '/download',
                    module: 'download',
                },
                'help': {
                    title: lang.routeTypes.help,
                    icon: 'fas fa-question-circle',
                    url: '/help',
                    module: 'help',
                },
                'bazaar': {
                    title: lang.routeTypes.bazaar,
                    icon: 'fas fa-store',
                    url: '/bazaar',
                    module: 'bazaar',
                },
                'gaming-night': {
                    title: lang.routeTypes.gamingNight,
                    icon: 'fas fa-moon',
                    url: '/gaming-night',
                    module: 'gaming_night',
                },
                'forum': {
                    title: lang.routeTypes.forum,
                    icon: 'fas fa-comment',
                    url: '/forum',
                    module: 'forum',
                },
                'staff': {
                    title: lang.routeTypes.staff,
                    icon: 'fas fa-crown',
                    url: '/staff',
                    module: 'staff',
                },
                'vote': {
                    title: lang.routeTypes.vote,
                    icon: 'fas fa-poll',
                    url: '/vote',
                    module: 'vote',
                },
                'punishments': {
                    title: lang.routeTypes.punishments,
                    icon: 'fas fa-ban',
                    url: '/punishments',
                    module: 'punishments',
                },
                'suggestions': {
                    title: lang.routeTypes.suggestions,
                    icon: 'fas fa-thumbs-up',
                    url: '/suggestions',
                    module: 'suggestions',
                },
                'changelog': {
                    title: lang.routeTypes.changelog,
                    icon: 'fas fa-check',
                    url: '/changelog',
                    module: 'changelog',
                }
            }
            this.footerMenuModel.title = types[type].title;
            this.footerMenuModel.icon = types[type].icon;
            this.footerMenuModel.url = types[type].url;
            this.footerMenuModel.route = type;
            this.footerMenuModel.tab = '0';
            this.footerMenuModel.module = types[type].module;
        },
    };
}

function advancedProductListing() {
    return {
        results: [],
        saveChanges() {
            $request('/dashboard/store/products/order', {
                json: JSON.stringify(this.results)
            }, 'POST')
                .then(response => response.data)
                .then(response => {
                    if (response.status) {
                        this.$dispatch('notice', {
                            type: 'success',
                            title: lang.alert_title_success,
                            text: response.message
                        })
                    }
                    else {
                        this.$dispatch('notice', {
                            type: 'error',
                            title: lang.alert_title_error,
                            text: ""
                        })
                    }
                });
        },
        init() {
            const nestableContainer = $('#advanced-product-listing')
            const options = {
                callback: () => {
                    const before = JSON.stringify(Object.values(this.results))
                    const nestableContainer = $('#advanced-product-listing')
                    this.results = nestableContainer.nestable("serialize")

                    if (before !== JSON.stringify(this.results)) {
                        this.saveChanges();
                        console.log(this.results)
                    }
                },
                beforeDragStop: function(l,e, p) {
                    // l is the main container
                    // e is the element that was moved
                    // p is the place where element was moved.
                    const sourceType = e[0].dataset.type;
                    const sourceGroupID = e[0].dataset.groupId;
                    const destinationType = p[0].dataset.type;
                    const destinationGroupID = p[0].dataset.groupId;

                    if (sourceType === 'category' && destinationType === undefined && sourceGroupID === '0' && p[0].parentElement.dataset.type === 'product') {
                        return false;
                    }
                    if (sourceType === 'category' && destinationType === undefined && sourceGroupID !== '0') {
                        return false;
                    }
                    if (sourceType === 'category' && destinationType === "group" && sourceGroupID !== destinationGroupID) {
                        return false;
                    }
                    if (sourceType === 'product' && sourceGroupID !== destinationGroupID) {
                        return false;
                    }
                }
            }
            nestableContainer.nestable(options)
            this.results = nestableContainer.nestable("serialize");
        }
    }
}

function datePicker(options = {}) {
    return {
        init() {
            this.$nextTick(() => {
                const el = this.$el;
                flatpickr(el, {
                    locale: language,
                    enableTime: true,
                    dateFormat: "Y-m-d H:i",
                    altInput: true,
                    altFormat: "d F Y H:i",
                    time_24hr: true,
                    minDate: "today",
                    defaultDate: (el.value) ? el.value : null,
                    ...options,
                })
            })
        }
    }
}

function datePickerWithCheckbox(initialDate, options = {}) {
    return {
        date: initialDate,
        placeholder: '',
        isDisabled: initialDate === '1000-01-01 00:00:00', // Checkbox initial state
        flatpickrInstance: null, // Flatpickr instance
        init() {
            // data-placeholder
            this.placeholder = this.$refs.datepicker.getAttribute('data-placeholder');
            
            // Initialize Flatpickr
            this.flatpickrInstance = flatpickr(this.$refs.datepicker, {
                locale: language,
                enableTime: true,
                dateFormat: "Y-m-d H:i",
                altInput: true,
                altFormat: "d F Y H:i",
                time_24hr: true,
                minDate: "today",
                defaultDate: this.date !== '1000-01-01 00:00:00' ? this.date : null,
                ...options,
                onChange: (selectedDates, dateStr) => {
                    // When the date changes, ensure the checkbox is unchecked
                    if (dateStr) {
                        this.isDisabled = false;
                        this.$refs.neverCheckbox.checked = false;
                    }
                },
            });
            
            // Update input and checkbox state on initialization
            this.updateInputState();
        },
        updateInputState() {
            if (this.isDisabled) {
                // Clear the Flatpickr value and disable both inputs
                this.flatpickrInstance.clear();
                this.$refs.datepicker.disabled = true; // Original input
                this.flatpickrInstance.altInput.disabled = true; // Flatpickr altInput
                this.$refs.neverCheckbox.checked = true;
            } else {
                // Enable both inputs and uncheck the checkbox
                this.$refs.datepicker.disabled = false; // Original input
                this.flatpickrInstance.altInput.disabled = false; // Flatpickr altInput
                this.$refs.neverCheckbox.checked = false;
            }
            
            this.flatpickrInstance.altInput.setAttribute('placeholder', this.isDisabled ? 'n/a' : this.placeholder);
        },
        toggleCheckbox() {
            // Toggle the checkbox state and update input states
            this.isDisabled = !this.isDisabled;
            if (this.isDisabled) {
                // Clear the Flatpickr value when disabling the input
                this.flatpickrInstance.clear();
            }
            this.updateInputState();
        },
    };
}



function statsDatePicker() {
    return {
        init() {
            this.$nextTick(() => {
                const el = this.$el;
                flatpickr(el, {
                    locale: language,
                    altInput: true,
                    altFormat: "d F Y",
                    dateFormat: "Y-m-d",
                    defaultDate: (el.value) ? el.value : null,
                })
            })
        }
    }
}

function iconPicker() {
    return {
        open: false,
        icons: [],
        search: '',
        filteredIcons: [],
        selectedIcon: '',

        perPage: 25,
        page: 1,
        totalPage: 0,
        init() {
            // https://furcan.github.io/IconPicker/dist/iconpicker-1.5.0.json
            let path = '/apps/dashboard/public/assets/icons6.json'
            fetch(path)
                .then(response => response.json())
                .then(data => {
                    this.icons = data
                    this.totalPage = Math.ceil(Object.values(data).length / this.perPage)
                })

            this.$watch('search', () => this.page = 1)
        },
        selectIcon(icon) {
            this.selectedIcon = this.selectedIcon === icon ? '' : icon
            this.open = false
        },
        getPage() {
            const start = (this.page - 1) * this.perPage
            const end = this.page * this.perPage

            this.filteredIcons = this.icons
            if (this.search)
                this.filteredIcons = Object.values(this.icons).filter(data =>
                    data.toLowerCase().includes(this.search.toLowerCase())
                )

            this.totalPage = Math.ceil(Object.values(this.filteredIcons).length / this.perPage)
            return Object.values(this.filteredIcons).slice(start, end)
        },
        nextIcons() {
            let pageToNum = parseInt(this.page)
            if (pageToNum !== this.totalPage + 1)
                this.page = pageToNum + 1 !== this.totalPage + 1 ? pageToNum + 1 : pageToNum
        },
        prevIcons() {
            let pageToNum = parseInt(this.page)
            if (pageToNum !== 1)
                this.page = pageToNum - 1 !== this.totalPage ? pageToNum - 1 : pageToNum
        }
    }
}

function colorPicker() {
    return {
        init() {
            this.$nextTick(() => {
                Coloris({
                    el: '.coloris',
                    theme: 'pill',
                    themeMode: 'light',
                    formatToggle: true,
                    closeButton: false,
                    clearButton: true,
                    swatches: [
                        '#067bc2',
                        '#84bcda',
                        '#80e377',
                        '#ecc30b',
                        '#f37748',
                        '#d56062'
                    ]
                });
            })
        }
    }
}

function codeMirror(lang = 'css', theme = 'material-ocean', lineNumbers = true) {
    return {
        editor: null,
        textarea: null,
        lang: lang,
        init() {
            this.$nextTick(() => {
                this.textarea = this.$refs.editor
                this.editor = CodeMirror.fromTextArea(this.textarea, {
                    mode: lang,
                    theme: theme,
                    lineNumbers: lineNumbers,
                })

                this.editor.on('change', () => this.editor.getValue())
            });
        }
    }
}

/**
 * Dropdown
 *
 * @param placement
 * - top.right - top.left
 * - bottom.right - bottom.left
 * @returns {any}
 */
function dropdown(placement = 'top.right') {
    return {
        show: false,
        selected: null,
        init() {
          // Find selected class
          const selected = this.$el.querySelectorAll('.dropdown > .active')[0];
          if (selected) {
            this.selected = selected.textContent;
          } else {
            this.selected = this.$el.querySelectorAll('.dropdown > *:first-child')[0].textContent;
          }
        },
        toggle() {
            this.show = !this.show
        },
        isDropdown: {
            ['x-show']() {
                return this.show
            },
            ['x-transition.origin.' + placement]() {
            },
            ['@click.outside']() {
                this.show = false
            }
        }
    }
}

function roles() {
    return {
        selector: null,
        showDateModal: false,
        dateSettings: '{}',
        dateSettingsModel: {
            id: '',
            name: '',
            status: false,
            date: ''
        },
        init() {
            document.querySelector('HTML').addEventListener("keydown", (event) => {
                const keyCode = event.keyCode || event.which
                if (keyCode === 27 && this.showDateModal !== false) this.showDateModal = false;
            })
        },
        roleSelector(roles = [], userPermissions = [], dateSettings = {}) {
            this.dateSettings = dateSettings;

            this.$nextTick(() => {
                const onChange = (target, userPermissions = []) => {
                    // Reset selections
                    $('input[id^="permission_"]').prop("checked", false).prop("disabled", false);

                    // Select user permissions
                    userPermissions.map(permission => {
                        $("#permission_" + permission).prop("checked", true);
                    });

                    // Create role permissions array
                    let rolePermissions = []
                    for (const option of target.options) {
                        if (option.selected) {
                            rolePermissions = [...rolePermissions, ...JSON.parse(option.dataset.permissions)]
                        }
                    }

                    // Select and disable role permissions
                    rolePermissions.map(permission => {
                        $(`#permission_${permission}`).prop("checked", true).prop("disabled", true);
                    });

                    // Update dateSettings
                    const expiryDates = JSON.parse(this.dateSettings || '{}');
                    let roleDateSettings = {};
                    for (const option of target.selectedOptions) {
                        if (!option.disabled) {
                            roleDateSettings[option.value] = expiryDates[option.value] || '1000-01-01 00:00:00';
                        }
                    }
                    this.dateSettings = JSON.stringify(roleDateSettings);
                }

                // Add User role
                roles.push(1);

                // Format State
                function formatState (state) {
                    if (!state.id) {
                        return state.text.trim();
                    }

                    const dateSettingsJSON = $('input[name="roleDateSettings"]').val();
                    const expiryDates = JSON.parse(dateSettingsJSON || '{}');
                    var expiryDate = expiryDates[state.id] || '';

                    if (state.disabled) {
                        var $state = $(
                            '<span class="select2-selection__choice__role"><span></span></span>'
                        );
                    } else {
                        var $state = $(
                            '<span class="select2-selection__choice__role"><span></span><svg id="dateButton_' + state.id + '" class="select2-selection__choice__role_date focus:outline-none" x-bind="tooltip(\'' + ((expiryDate === '' || expiryDate === '1000-01-01 00:00:00') ? lang.lifetime : expiryDate) + '\')" @click="openDateModal(\''+ state.id +'\', \''+ state.text.trim().replace("'", "\'") +'\', \'' + expiryDate + '\')" xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none"></svg></span>'
                        );
                    }

                    // Use .text() instead of HTML string concatenation to avoid script injection issues
                    $state.find("span").text(state.text.trim());
                    $state.find("svg").html('<path d="M22 12c0 5.52-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2s10 4.48 10 10Z" stroke="#2563eb" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="m15.71 15.18-3.1-1.85c-.54-.32-.98-1.09-.98-1.72v-4.1" stroke="#2563eb" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>');

                    return $state;
                }

                // Init select2
                const el = $(this.$el);
                this.selector = el.select2({
                    templateSelection: formatState
                });
                el.val(roles).trigger('change');

                // Init selections
                onChange(this.$el, userPermissions);

                // Disable remove user role
                this.selector.on('select2:unselecting', function (e) {
                    if (e.params.args.data.disabled === true) {
                        e.preventDefault();
                    }
                });

                // On change
                this.selector.on('change', function (e) {
                    onChange(e.target, userPermissions);
                });
            });
        },
        openDateModal(roleId, name, date = '') {
            date = JSON.parse(this.dateSettings)[roleId] || date;
            this.dateSettingsModel.id = roleId;
            this.dateSettingsModel.name = name;
            this.dateSettingsModel.status = (date !== '' && date !== '1000-01-01 00:00:00') ? '1' : '0';
            this.dateSettingsModel.date = (date !== '' && date !== '1000-01-01 00:00:00') ? date : '';

            this.roleDatePicker(this.$refs.roleDatePicker);

            this.showDateModal = true;
            setTimeout(() => {
                this.selector.select2('close');
            }, 1);
        },
        hideDateModal() {
            this.showDateModal = false;
        },
        updateDate() {
            let dateSettingsJSON = JSON.parse(this.dateSettings);
            if (this.dateSettingsModel.status === '0' || this.dateSettingsModel.date === '') {
                this.dateSettingsModel.date = '1000-01-01 00:00:00';
            }
            dateSettingsJSON[this.dateSettingsModel.id] = this.dateSettingsModel.date;
            this.dateSettings = JSON.stringify(dateSettingsJSON);

            // Update Tooltip
            $('#dateButton_' + this.dateSettingsModel.id).attr('x-bind', "tooltip('" + (this.dateSettingsModel.date === '1000-01-01 00:00:00' ? lang.lifetime : this.dateSettingsModel.date) + "')");

            this.hideDateModal();
        },
        roleDatePicker(el) {
            this.$nextTick(() => {
                flatpickr(el, {
                    locale: language,
                    enableTime: true,
                    dateFormat: "Y-m-d H:i",
                    altInput: true,
                    altFormat: "d F Y H:i",
                    time_24hr: true,
                    minDate: "today",
                    defaultDate: (el.value) ? el.value : null,
                })
            })
        }
    }
}

function selectVIPs() {
    return {
        select2: null,
        values: [],
        init() {
            this.$nextTick(() => {
                const placeholder = this.$el.getAttribute('placeholder')
                this.select2 = $(this.$el).select2({
                    placeholder: placeholder,
                })

                this.select2.on('change', event => {
                    this.values = $(event.target).val();
                })
            })
        },
        onChange(func = () => {}) {
            this.$nextTick(() => {
                this.$watch('values', (values) => {
                    func(values)
                });
            })
        }
    }
}

function sortable() {
    return {
        sortable: null,
        init() {
            this.$nextTick(() => {
                this.sortable = new Sortable(this.$el, {
                    handle: '.draggable-item',
                    animation: 150
                });
            });
        }
    }
}

function sendAgainCommand(id, status, dateLong, dateShort) {
    return {
        status: status,
        dateLong: dateLong,
        dateShort: dateShort,
        isLoading: false,
        sendAgain() {
            if (this.isLoading) return;

            this.isLoading = true;
            $request('/dashboard/command-logs/send/' + id)
                .then(response => response.data)
                .then(data => {
                    if (data.status === 'completed' || data.status === 'sending') {
                        this.$dispatch('notice', {
                            type: 'success',
                            title: lang.alert_title_success,
                            text: data.message
                        })
                        this.status = data.status;
                    } else {
                        this.$dispatch('notice', {
                            type: 'error',
                            title: lang.alert_title_error,
                            text: data.message
                        })
                        this.status = 'error';
                    }

                    if (data.dateLong && data.dateShort) {
                        this.dateLong = data.dateLong;
                        this.dateShort = data.dateShort;
                    }

                    this.isLoading = false;
                })
        }
    }
}

function deleteConfirmation() {
    return {
        init() {
            const form = this.$el;
            form.getElementsByTagName('button')[0].addEventListener('click', (event) => {
               event.preventDefault();
                this.$dispatch('open-alert', {
                    type: 'delete',
                    title: lang.alert_title_warning,
                    message: lang.delete_selected_confirm_message,
                    confirm: function() {
                        form.submit();
                    },
                    confirmText: lang.alert_btn_delete
                })
            });
        },
    }
}

function serverToken(token, resetUrl) {
    return {
        showToken: false,
        isLoading: false,
        token: token,
        resetServerToken() {
            this.isLoading = true;
            $request(resetUrl).then(response => response.data).then(result => {
                if (result.status) {
                    this.token = result.token;
                    this.showToken = true;
                    this.$dispatch('notice', {
                        type: 'success',
                        title: lang.alert_title_success,
                        text: result.message
                    });
                } else {
                    this.$dispatch('notice', {
                        type: 'error',
                        title: lang.alert_title_error,
                        text: result.message
                    })
                }
                this.isLoading = false;
            });
        },
    }
}

function listjs() {
    return {
        listjs: null,
        init() {
            // Find values
            const valueNames = [];
            // Find data-sort attribute with css selector
            const sortValues = this.$el.querySelectorAll('[data-sort]');
            sortValues.forEach(row => {
                valueNames.push(row.getAttribute('data-sort'));
            });

            this.$nextTick(() => {
                this.listjs = new List('listjs', {
                    valueNames
                });
            });
        }
    }
}

function search() {
    return {
        query: '',
        index: null,
        results: [],
        loading: false,
        notFound: false,
        search() {
            if (this.query === '' || this.query.length < 3) {
                this.results = [];
                this.notFound = false;
                return;
            }
            
            this.loading = true;
            this.notFound = false;
            
            axios.get('/dashboard/ajax/search', {
                params: {
                    query: this.query
                }
            })
              .then(response => response.data)
              .then(data => {
                  this.loading = false;
                  this.results = data;
                  
                  if (data.length === 0) {
                      this.notFound = true;
                  } else {
                      this.results.map(result => {
                          // Replace %sep% to svg
                          result.item.breadcrumb = result.item.breadcrumb.replace(/>/g, '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right w-5 h-5 search-separator"><polyline points="9 18 15 12 9 6"></polyline></svg>');
                      });
                  }
              });
        },
        init() {
            this.$watch('query', (val) => {
                this.search();
            })
        }
    }
}

function unlimitedInput(limit = -1) {
    return {
        limit: -1,
        isUnlimited: false,
        init() {
            this.limit = limit;
            this.isUnlimited = this.limit === -1;
        }
    }
}

function getCategories() {
    return axios.get('/dashboard/ajax/store/categories')
        .then(response => response.data);
}
function getProductsByCategory(categoryID) {
    return axios.get('/dashboard/ajax/store/products/getByCategory?categoryID=' + categoryID)
      .then(response => response.data);
}

document.addEventListener("DOMContentLoaded", function () {
    const unlimitedInputs = document.querySelectorAll('[data-toggle="unlimited-input"]');
    
    unlimitedInputs.forEach((inputGroup) => {
        const limitInput = inputGroup.querySelector('input[type="number"]');
        const unlimitedCheckbox = inputGroup.querySelector('input[type="checkbox"]');
        
        // Get the data-limit value
        let limit = parseInt(inputGroup.getAttribute('data-limit'), 10);
        if (limit === -1) {
            limitInput.value = '';
            limitInput.disabled = true; // Initially disabled
            unlimitedCheckbox.checked = true; // Unlimited option is checked
        } else {
            limitInput.value = limit;
            limitInput.disabled = false; // Not disabled
        }
        
        unlimitedCheckbox.addEventListener("change", function () {
            if (this.checked) {
                limitInput.value = ''; // Clear value
                limitInput.disabled = true; // Disable input
            } else {
                limitInput.disabled = false; // Enable input
                limitInput.value = limit; // Restore limit value
                if (limit === -1) {
                    limitInput.value = ''; // Set to empty if limit is -1
                }
            }
        });
        
        limitInput.addEventListener("input", function () {
            if (this.value === '') {
                limit = -1; // If input is empty, set limit to -1
            } else {
                limit = parseInt(this.value, 10); // Set value
            }
        });
    });
});

// Form submit loading button
document.addEventListener("DOMContentLoaded", function () {
    const forms = document.querySelectorAll('form[data-submit-loading]');
    
    forms.forEach((form) => {
        const button = form.querySelector('button[type="submit"]');
        const buttonHeight = button.offsetHeight;
        form.addEventListener("submit", function () {
            button.disabled = true;
            button.style.pointerEvents = 'none';
            button.style.opacity = '0.5';
            button.style.height = buttonHeight + 'px';
            button.innerHTML = lang.loading;
        });
    });
});

function unlinkDiscord(url) {
    return {
        isLoading: false,
        unlinkDiscordRequest() {
            this.isLoading = true;
            $request(url).then(response => response.data).then(result => {
                window.location.reload();
            });
        },
    }
}

function unlinkDiscordBot(url) {
    return {
        isLoading: false,
        unlinkDiscordBotRequest() {
            // Confirm
            this.$dispatch('open-alert', {
                type: 'warning-question',
                title: lang.alert_title_warning,
                message: lang.alert_message_unlink_discord_bot_confirm_message,
                confirm: () => {
                    this.isLoading = true;
                    $request(url).then(response => response.data).then(result => {
                        window.location.reload();
                    });
                },
                confirmText: lang.alert_btn_confirm
            });
        },
    }
}

function generateRandomCode() {
    return {
        generate() {
            this.$refs.codeInput.value = Math.random().toString(36).substring(2, 8).toUpperCase();
        }
    }
}