const puockGlobalData = {
    loads: {}
}

const TYPE_PRIMARY = "primary"
const TYPE_WARNING = "warning"
const TYPE_DANGER = "danger"
const TYPE_SUCCESS = "success"
const TYPE_INFO = "info"

class Puock {

    data = {
        tag: 'puock',
        pc:true,
        params: {
            home: null,
            use_post_menu: false,
            is_single: false,
            is_pjax: false,
            vd_comment: false,
            vd_gt_id: null,
            vd_type: null,
            main_lazy_img: false,
            link_blank_open: false,
            async_view_id: null,
            mode_switch: false,
            async_view_generate_time: null,
            off_img_viewer:false,
            off_code_highlighting:false
        },
        comment: {
            loading: false,
            time: 5,
            val: null,
            replyId: null
        },
        instance: {},
        modalStorage: {}
    }

    // 全局一次加载或注册的事件
    onceInit() {
        this.pageInit()
        $(document).on("click", ".fancybox", () => {
            return false;
        });
        $(document).on("click", "#rb-float-actions>div", (e) => {
            const el = $(this.ct(e));
            const to = el.data("to");
            if (to) {
                const scroll_val = to === 'top' ? 0 : window.document.body.clientHeight;
                $('html,body').stop().animate({scrollTop: scroll_val}, 50)
                return;
            }
            const toArea = el.data("to-area");
            if (toArea) {
                this.gotoArea(toArea)
            }
        });
        $(document).on("click", ".colorMode", () => {
            this.modeChange(null, true);
        });

        if (this.data.params.is_pjax) {
            this.instanceClickLoad()
        }
        this.initBasicDOMEvent()
        this.sidebarMenuEventInit()
        this.searchInit()
        this.eventShareStart()
        this.modeInit();
        this.registerMobileMenu()
        this.registerModeChangeEvent()
        this.eventCommentPageChangeEvent()
        this.eventCommentPreSubmit()
        this.eventSendPostLike()
        this.eventPostMainBoxResize()
        this.swiperOnceEvent()
        this.initModalToggle()
        this.detectDevice()
        window.addEventListener('resize', ()=>this.detectDevice());
        layer.config({shade: 0.5})
        // 新增：首次加载时初始化评论相关事件
        this.initCommentEvents();
    }

    pageInit() {
        this.loadParams()
        this.pageChangeInit()
        if (this.data.params.is_single) {
            if (this.data.params.use_post_menu) {
                this.generatePostMenuHTML()
            }
        }
    }

    instanceClickLoad() {
        InstantClick.init('mousedown');
        InstantClick.go = (url) => {
            const link = document.createElement('a');
            link.href = url;
            document.body.appendChild(link);
            link.click();
        }
        InstantClick.on('change', (e) => {
            this.loadParams();
            this.pageChangeInit()
        })
        // InstantClick.on('receive',(url, body, title)=>{
        //     console.log(body)
        //     this.loadParams($(body))
        // })
        this.loadCommentInfo();
    }

    ct(e) {
        return e.currentTarget
    }

    detectDevice() {
        const screenWidth = window.innerWidth;
        this.data.pc = screenWidth >= 768
    }

    initBasicDOMEvent() {
        // el show or hide event
        $(document).on("click", ".toggle-el-show-hide", (e) => {
            const el = $(this.ct(e));
            const target = $(el.attr("data-target"));
            const self = $(el.attr("data-self"));
            const modalTitle = el.attr("data-modal-title");
            if (target.hasClass("d-none")) {
                self.addClass("d-none");
                target.removeClass("d-none");
            } else {
                self.removeClass("d-none");
                target.addClass("d-none");
            }
            if (modalTitle) {
                el.closest(".modal").find(".modal-title").text(modalTitle);
            }
        });
        // form ajax submit
        $(document).on("submit", ".ajax-form", (e) => {
            // 如果是登录弹窗表单，允许原生提交
            if ($(e.target).attr('id') === 'front-login-form') {
                return true;
            }
            e.preventDefault();
            const form = $(this.ct(e));
            const formEls = form.find(":input")
            if (formEls.length === 0) {
                this.toast('表单元素为空', TYPE_DANGER)
                return false;
            }
            for (let i = 0; i < formEls.length; i++) {
                const el = $(formEls[i]);
                if (el.attr("data-required") !== undefined && el.val() === "") {
                    this.toast(el.attr("data-tip") || el.attr("placeholder"), TYPE_WARNING)
                    return false;
                }
            }
            const validateType = form.data("validate");
            const startSubmit = (args = {}) => {
                const url = form.attr("action");
                const method = form.attr("method");
                const data = this.parseFormData(form, args);
                const dataType = "json";
                const successTip = form.attr("data-success");
                const errorTip = form.attr("data-error");
                const loading = this.startLoading()
                $.ajax({
                    url, method, data, dataType,
                    success: (res) => {
                        this.stopLoading(loading)
                        if (res.code === 0 || res.success) {
                            this.toast(res.msg || successTip, TYPE_SUCCESS)
                            if (form.data("no-reset") === undefined) {
                                form.trigger("reset")
                            }
                            if (res.data) {
                                const resData = res.data
                                if (resData.action) {
                                    setTimeout(() => {
                                        switch (resData.action) {
                                            case 'reload':
                                                this.goUrl(window.location.href)
                                                break
                                        }
                                    }, 500)
                                }
                            }
                        } else {
                            this.toast(res.msg || res.data || errorTip, TYPE_DANGER)
                        //    this.loadCommentCaptchaImage(form, true)
                        }
                    },
                    error: (e) => {
                        this.stopLoading(loading)
                        this.toast(`请求错误：${e.statusText}`, TYPE_DANGER)
                    //    this.loadCommentCaptchaImage(form, true)
                    }
                })
            }
            if (validateType === 'gt') {
                this.gt.validate((code) => {
                    startSubmit(code)
                });
            } else {
                startSubmit()
            }
            return false;
        })
        // 登录弹窗表单AJAX提交（集成Puock插件接口）
        $(document).off('submit', '#front-login-form');
        $(document).on('submit', '#front-login-form', function(e) {
            e.preventDefault();
            var $form = $(this);
            var data = $form.serialize();
            $.ajax({
                url: '/index.php/ajaxlogin/',
                type: 'POST',
                data: data,
                dataType: 'json',
                success: function(res) {
                    if (res.success) {
                        window.Puock.toast(res.msg || '登录成功', TYPE_SUCCESS);
                        setTimeout(function() {
                            window.location.reload();
                        }, 800);
                    } else {
                        window.Puock.toast(res.msg || '登录失败', TYPE_DANGER);
                    }
                },
                error: function() {
                    window.Puock.toast('请求失败', TYPE_DANGER);
                }
            });
        });
    }

    pageLinkBlankOpenInit() {
        if (this.data.params.link_blank_open) {
            $(".entry-content").find("a").each((_, item) => {
                $(item).attr('target', 'blank')
            })
        }
    }

    searchInit() {
        const toggle = () => {
            const search = $("#search");
            const open = search.attr("data-open") === "true";
            let tag = open ? 'Out' : 'In';
            search.attr("class", "animated fade" + tag + "Left");
            $("#search-backdrop").attr("class", "modal-backdrop animated fade" + tag + "Right");
            search.attr("data-open", !open);
            if (!open) {
                search.find("input").focus();
            }
        }
        $(document).on("click", ".search-modal-btn", () => {
            toggle();
        });
        $(document).on("click", "#search-backdrop", () => {
            toggle();
        })
        $(document).on("submit", ".global-search-form", (e) => {
            e.preventDefault();
            const el = $(this.ct(e));
            this.goUrl(el.attr("action") + "/?" + el.serialize())
        })
    }

    goUrl(url) {
        if (this.data.params.is_pjax) {
            InstantClick.go(url)
        } else {
            window.location.href = url
        }
    }

    gt = {
        validate: (success = undefined) => {
            this.data.instance.gt_callback = success
        //    this.data.instance.gt.showCaptcha();
        }
    }

    rippleInit() {
        const args = {
            debug: false,
            on: 'mousedown',
            opacity: 0.4,
            color: "var(--pk-c-light)",
            multi: false,
            duration: 0.6,
            rate: function (pxPerSecond) {
                return pxPerSecond;
            },
            easing: 'linear'
        }
        jQuery.ripple(".btn", args);
        jQuery.ripple(".ww", args);
    }

    eventShareStart() {
        $(document).on("click", ".share-to", (e) => {
            const id = $(this.ct(e)).attr("data-id");
            if (id === 'wx') return;
            const url = window.location.href;
            const title = $("#post-title").text();
            const wb_key = '';
            let to = null;
            switch (id) {
                case 'wb':
                    to = 'https://service.weibo.com/share/share.php?pic=&title=' + title + '&url=' + url + '&appkey=' + wb_key;
                    break;
                case 'qzone':
                    to = 'https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?title=' + title + '&url=' + url;
                    break;
                case 'tw':
                    to = 'https://twitter.com/intent/tweet?url=' + url;
                    break;
                case 'fb':
                    to = 'https://www.facebook.com/sharer.php?u' + url;
                    break;
            }
            if (to) window.open(to, '_blank');
        });
    }

    sidebarMenuEventInit() {
        let currentOpenSubMenu = null;
        $(document).on("touchend", ".post-menu-toggle", (e) => {
            e.preventDefault();
            this.toggleMenu();
        });
        $(document).on("click", ".post-menu-toggle", () => {
            this.toggleMenu();
        });
        $(document).on("click", ".post-menu-item", (e) => {
            const el = $(this.ct(e))
            const id = el.attr("data-id")
            if (currentOpenSubMenu) {
                const parentUl = el.parents("ul")
                let curClass = "post-menu-sub-" + currentOpenSubMenu
                while (true) {
                    if (typeof (curClass) === "undefined") {
                        break
                    }
                    const currentMenu = $("." + curClass)
                    const classStr = currentMenu.attr("class")
                    const und = typeof (classStr) == "undefined"
                    if (und || parentUl.attr("class") === currentMenu.attr("class")) {
                        break;
                    } else {
                        currentMenu.hide();
                        curClass = currentMenu.parents("ul").attr("class");
                    }
                }
            }
            const subMenu = $(".post-menu-sub-" + id)
            if (subMenu.length > 0) {
                subMenu.show()
                currentOpenSubMenu = id
            }
        });
        $(document).on("click", ".pk-menu-to", (e) => {
            const to = $(this.ct(e)).attr("href");
            const headerHeight = $("#header").innerHeight();
            $("html, body").stop().animate({
                scrollTop: ($(to).offset().top - headerHeight - 10) + "px"
            }, {
                duration: 50,
                easing: "swing"
            });
            if(!this.data.pc){
                this.toggleMenu()
            }
            return false;
        });
    }

    toggleMenu() {
        const menuContainer = $("#post-menus");
        const menuButton = $("#post-menu-state");
        const className = "data-open";
        const isOpen = menuButton.hasClass(className);
        
        if (isOpen) {
            // 关闭菜单
            menuContainer.removeClass("show");
            menuButton.removeClass(className);
        } else {
            // 打开菜单
            menuContainer.addClass("show");
            menuButton.addClass(className);
        }
    }

    lazyLoadInit(parent = null, el = '.lazy') {
        if (window.lozad) {
            const observer = lozad([el, 'img[data-lazy="true"]'], {
                rootMargin: '10px 0px',
                threshold: 0.1,
                enableAutoReload: true,
                load: (el) => {
                    el.classList.add('loaded');
                    el.src = el.getAttribute('data-src');
                }
            });
            observer.observe();
        }
    }

    loadParams() {
        this.data.params = puock_metas;
        //this.data.commentVd = this.data.params.vd_comment === 'on';
    }

    initReadProgress() {
        const readProgress = $("#page-read-progress .progress-bar");
        document.addEventListener('scroll', () => {
            const a = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight) * 100;
            readProgress.attr("style", "width:" + a.toFixed(0) + "%");
        });
    }

    tooltipInit(el = $("[data-bs-toggle=\"tooltip\"]")) {
        [...el].map(tooltipTriggerEl => {
            new bootstrap.Tooltip(tooltipTriggerEl, {
                placement: 'bottom', trigger: 'hover'
            })
        })
    }

    pageChangeInit() {
        this.initReadProgress()
        this.modeInit();
        this.loadCommentInfo();
        this.katexParse();
        this.initCodeHighlight();
        this.pageLinkBlankOpenInit()
        this.initGithubCard();
        this.keyUpHandle();
     //   this.loadHitokoto();
    //    this.asyncCacheViews();
        this.swiperInit();
     //   this.validateInit();
        this.rippleInit();
        if (this.data.params.use_post_menu) {
            this.generatePostMenuHTML()
        }
        this.tooltipInit()
        if(!this.data.params.off_img_viewer){
            jQuery(".entry-content").viewer({
                navbar: false,
                url: this.data.params.main_lazy_img ? 'data-src' : 'src'
            });
        }
        const cp = new ClipboardJS('.pk-copy', {
            text: (trigger) => {
                const t = $(trigger)
                let input = t.attr("data-cp-input")
                let el = t.attr("data-cp-el")
                let val = t.attr("data-cp-val")
                let func = t.attr("data-cp-func")
                let text;
                if(typeof func !=="undefined"){
                    text = window[func](t)
                }else if (typeof val !== "undefined") {
                    text = val
                } else if (typeof input !== "undefined") {
                    text = $(input).val()
                } else if (typeof el !== "undefined") {
                    text = $(el).text()
                } else {
                    text = t.text()
                }
                return text;
            },
        });
        cp.on("success", (e) => {
            let name = $(e.trigger).attr('data-cp-title') || "";
            this.toast(`复制${name}成功`)
        })
        cp.on("error", (e) => {
            let name = $(e.trigger).attr('data-cp-title') || "";
            this.toast(`复制${name}失败`, TYPE_DANGER)
        })
        this.lazyLoadInit()
       // $('#post-main, #sidebar').theiaStickySidebar({
       //     additionalMarginTop: 20
       // });
        // 新增：pjax切换后重新初始化评论相关事件
        this.initCommentEvents();
    }


    getPostMenuStructure() {
        $('.entry-content').find('h1,h2,h3,h4,h5,h6').each(function(index, el) {
        if (!$(el).attr('id')) {
        let safeText = $(el).text().trim().replace(/\s+/g, '-').replace(/[^\w\-]/g, '').toLowerCase();
        // 防止重复id
        let uniqId = safeText || `heading-${index}`;
        // 如果已经有相同id，添加序号
        let counter = 1;
        while($('#' + uniqId).length > 0) {
            uniqId = `${safeText}-${counter++}`;
        }
        $(el).attr('id', uniqId);
       }
    });
        let res = []
        for (let item of $(".entry-content").find('h1,h2,h3,h4,h5,h6')) {
            res.push({name: $(item).text().trim(), level: item.tagName.toLowerCase(), id: $(item).attr("id")})
        }
        return res
    }

    generatePostMenuHTML() {
        const menus = this.getPostMenuStructure();
        if (menus.length > 0) {
            let result = "<ul>";
            if (menus.length > 0) {
                const finalMenus = []
                let maxLevel = 6;
                const initChildren = (item) => {
                    item.children = []
                    return item
                }
                const getLevel = (item) => {
                    item.levelInt = parseInt(item.level.replace("h", ""))
                    if (item.levelInt < maxLevel) {
                        maxLevel = item.levelInt
                    }
                    return item.levelInt
                }
                const firstMenu = initChildren(menus[0])
                const firstLevel = getLevel(firstMenu)
                let loadIndex = 0;
                const eqLevelFn = (unMenu, parentMen) => {
                    const nextUnMenu = loadMenu(unMenu, parentMen)
                    if (nextUnMenu != null) {
                        if (getLevel(nextUnMenu) === getLevel(unMenu)) {
                            return eqLevelFn(nextUnMenu, parentMen)
                        }
                    }
                    return nextUnMenu;
                }
                const loadMenu = (menu, parentMenu) => {
                    if (loadIndex >= menus.length - 1) {
                        return null;
                    }
                    const nextIndex = ++loadIndex;
                    const nextMenu = initChildren(menus[nextIndex])
                    const nowLevel = getLevel(menu)
                    const nextLevel = getLevel(nextMenu)
                    let unknownMenu = null;
                    if (nextLevel === firstLevel) {
                        finalMenus.push(nextMenu)
                        unknownMenu = loadMenu(nextMenu, null)
                    } else if (nextLevel > nowLevel) {
                        menu.children.push(nextMenu)
                        unknownMenu = loadMenu(nextMenu, menu)
                    } else if (nextLevel === nowLevel && parentMenu != null) {
                        parentMenu.children.push(nextMenu)
                        unknownMenu = loadMenu(nextMenu, parentMenu)
                    } else {
                        return nextMenu
                    }
                    if (unknownMenu != null) {
                        const unknownLevel = getLevel(unknownMenu)
                        if (unknownLevel === nowLevel) {
                            parentMenu.children.push(unknownMenu)
                            unknownMenu = eqLevelFn(unknownMenu, parentMenu)
                        }
                    }
                    return unknownMenu
                }
                finalMenus.push(firstMenu)
                while (true) {
                    const unknownMenu = loadMenu(firstMenu, null)
                    if (unknownMenu == null) {
                        break
                    }
                    loadMenu(unknownMenu, null)
                }
                let menuIndex = 0;
                const outHtml = (item, parent) => {
                    ++menuIndex;
                    const id = menuIndex;
                    const pl = (item.levelInt - maxLevel) * 10
                    let out = `<li data-level="${item.levelInt}" style='padding-left:${pl}px'>`
                    out += `<a class='pk-menu-to a-link t-w-400 t-md post-menu-item' data-parent="${parent}" data-id="${id}" href='#${item.id}'><i class='fa ${item.children.length > 0 ? 'fa-angle-right' : 'fa-file-invoice'} t-sm c-sub mr-1'></i> ${item.name}</a>`
                    if (item.children.length > 0) {
                        out += `<ul class="post-menu-sub-${id}" data-parent="${parent + 1}">`
                        for (let child of item.children) {
                            out += outHtml(child, id)
                        }
                        out += `</ul>`
                    }
                    out += "</li>"
                    return out;
                }
                finalMenus.forEach(item => {
                    result += outHtml(item, menuIndex)
                })
            }
            result += "</ul>"
            $("#post-menu-content-items").html(result);
            $(".post-menus-box").show();
        }
    }

    initCodeHighlight(fullChange = true, bodyEl="body") {
        if(this.data.params.off_code_highlighting){
            return
        }
        if (window.hljs !== undefined) {
            window.hljs.configure({ignoreUnescapedHTML: true})
            $(bodyEl).find("pre").each((index, block) => {
                const el = $(block);
                const codeChildClass = el.children("code") ? el.children("code").attr("class") : undefined;
                if (codeChildClass) {
                    if (codeChildClass.indexOf("katex") !== -1 || codeChildClass.indexOf("latex") !== -1 || codeChildClass.indexOf("flowchart") !== -1
                        || codeChildClass.indexOf("flow") !== -1 || codeChildClass.indexOf("seq") !== -1 || codeChildClass.indexOf("math") !== -1) {
                        return;
                    }
                }
                if (!el.attr("id")) {
                    el.attr("id", "hljs-item-" + index)
                    el.before("<div class='pk-code-tools' data-pre-id='hljs-item-" + index + "'><div class='dot'>" +
                        "<i></i><i></i><i></i></div><div class='actions'><div><i class='i fa fa-copy cp-code' data-clipboard-target='#hljs-item-" + index + "'></i></div></div></div>")
                    window.hljs.highlightBlock(block);
                    window.hljs.lineNumbersBlock(block);
                }
            });
            if (fullChange) {
                const cp = new ClipboardJS('.cp-code');
                cp.on("success", (e) => {
                    e.clearSelection();
                    this.toast('已复制到剪切板')
                })
            }
        }
    }

    localstorageToggle(name, val = null) {
        return val != null ? localStorage.setItem(name, val) : localStorage.getItem(name);
    }

    loadCommentInfo() {
        const authorText = this.localstorageToggle("comment_author"),
            emailText = this.localstorageToggle("comment_email"),
            urlText = this.localstorageToggle("comment_url");
        if (authorText != null && emailText != null) {
            $("#comment_author").val(authorText);
            $("#comment_email").val(emailText);
            $("#comment_url").val(urlText);
        }
    }

    setCommentInfo() {
        this.localstorageToggle("comment_author", $("#comment_author").val());
        this.localstorageToggle("comment_email", $("#comment_email").val());
        this.localstorageToggle("comment_url", $("#comment_url").val());
    }

    modeInit() {
        this.modeChange();
    }

    modeChange(toLight = null, isSwitch = false) {
        const body = $("body");
        if (typeof (toLight) === "string") {
            toLight = toLight === 'true';
        }
        let mode = Cookies.get('mode') || 'auto'
        if (toLight === null) {
            toLight = mode==='light';
            if(mode==='auto'){
                toLight = !window.matchMedia('(prefers-color-scheme:dark)').matches
            }
        }
        if (isSwitch) {
            if(mode==='light'){
                mode = 'dark'
                toLight = false;
            }else if(mode==='dark'){
                mode = 'auto'
                toLight = !window.matchMedia('(prefers-color-scheme:dark)').matches;
            }else{
                mode = 'light'
                toLight = true;
            }
            console.log(mode, toLight)
        }
        let dn = 'd-none';
        if (toLight) {
            $("#logo-light").removeClass(dn);
            $("#logo-dark").addClass(dn);
        } else {
            $("#logo-dark").removeClass(dn);
            $("#logo-light").addClass(dn);
        }
        $(".colorMode").each((_, e) => {
            const el = $(e);
            let target;
            if (el.prop("localName") === 'i') {
                target = el;
            } else {
                target = $(el).find("i");
            }
            if (target) {
                target.removeClass("fa-sun").removeClass("fa-moon").removeClass('fa-circle-half-stroke')
                    .addClass(mode==='auto' ? 'fa-circle-half-stroke' : (mode==='light' ? "fa-sun" : "fa-moon"));
            }
        })
        body.removeClass(this.data.tag + "-auto")
        body.removeClass(toLight ? this.data.tag + "-dark" : this.data.tag + "-light");
        body.addClass(toLight ? this.data.tag + "-light" : this.data.tag + "-dark");
        // this.localstorageToggle('light', toLight)
        Cookies.set('mode', mode)
    }

    modeChangeListener() {
        if(Cookies.get('mode')==='auto'){
            this.modeChange(!window.matchMedia('(prefers-color-scheme:dark)').matches);
        }
    }

    registerModeChangeEvent() {
        if (this.data.params.mode_switch) {
            try {
                window.matchMedia('(prefers-color-scheme:dark)').addEventListener('change', () => {
                    this.modeChangeListener()
                });
            } catch (ex) {
                window.matchMedia('(prefers-color-scheme:dark)').addListener(() => {
                    this.modeChangeListener()
                });
            }
        }
    }

    infoToastShow(text, title = '提示') {
        const infoToast = $('#infoToast');
        $("#infoToastTitle").html(title);
        $("#infoToastText").html(text);
        infoToast.modal('show');
    }

    registerMobileMenu() {
        const fn = (s) => {
            if (typeof (s) !== 'string') {
                s = 'Out'
            }
            $("#mobile-menu").attr("class", "animated fade" + s + "Left");
            $("#mobile-menu-backdrop").attr("class", "modal-backdrop animated fade" + s + "Right");
        }
        $(document).on("click", "#mobile-menu-backdrop", fn);
        $(document).on("click", ".mobile-menu-close", fn);
        $(document).on("click", ".mobile-menu-s", () => {
            fn('In');
        });
    }

    gotoArea(el, speed = 50) {
        const top = $(el).offset().top - $("#header").height() - 10;
        $('html,body').stop().animate({scrollTop: top}, speed);
    }

    pushAjaxCommentHistoryState(href) {
        history.pushState({foo: "bar"}, "page 2", href);
    }

    eventCommentPageChangeEvent() {
        $(document).on('click', '.comment-ajax-load a.page-numbers', (e) => {
            const postCommentsEl = $("#post-comments");
            const loadBox = $("#comment-ajax-load");
            $("#comment-cancel").click();
            let href = $(this.ct(e)).attr("href");
            this.pushAjaxCommentHistoryState(href);
            postCommentsEl.html(" ");
            this.gotoArea("#comments");
            loadBox.removeClass('d-none');
            $.post(href, {}, (data) => {
                postCommentsEl.html($(data).find("#post-comments"));
                loadBox.addClass('d-none');
                this.initCodeHighlight(false);
                this.lazyLoadInit(postCommentsEl);
            }).fail(() => {
                location = href;
            });
            return false;
        })

    }

    parseFormData(formEl, args = {}) {
        // 先获取表单所有字段
        const dataArr = formEl.serializeArray();
        const data = {};
        for (let i = 0; i < dataArr.length; i++) {
            data[dataArr[i].name] = dataArr[i].value;
        }
        // 合并额外参数
        return jQuery.param(Object.assign(data, args));
    }

    eventCommentPreSubmit() {
        $(document).on('submit', '#comment-form', (e) => {
            e.preventDefault();
            if ($("#comment-logged").val() === '0' && ($.trim($("#comment_author").val()) === '' || $.trim($("#comment_email").val()) === '')) {
                this.toast('评论信息不能为空', TYPE_WARNING);
                return;
            }
            if ($.trim($("#comment").val()) === '') {
                this.toast('评论内容不能为空', TYPE_WARNING);
                return;
            }
            if (this.data.params.vd_comment) {
                if (this.data.params.vd_type === 'img') {
                    if ($.trim($("#comment-vd").val()) === '') {
                        this.toast('验证码不能为空', TYPE_WARNING);
                        return;
                    }
                } else {
                    this.gt.validate((code) => {
                        this.commentSubmit(this.ct(e), code)
                    })
                    return;
                }
            }
            this.commentSubmit(this.ct(e))
        })
    }

    commentSubmit(target, args = {}) {
    let submitUrl = $("#comment-form").attr("action");
    this.commentFormLoadStateChange();
    const el = $(target);
    
    $.ajax({
        url: submitUrl,
        data: this.parseFormData(el, args),
        type: el.attr('method'),
        success: (data) => {
            this.toast('评论已提交成功', TYPE_SUCCESS);
            $("#comment-vd").val("");
            $("#comment").val("");
            
            // 获取整个评论区域的新内容
            const newComments = $(data).find("#comments").html();
            
            // 替换当前评论区域
            $("#comments").html(newComments);
            
            // 重置评论表单状态
            $("#comment-form").trigger("reset");
            $("#comment-cancel").click();
            this.commentFormLoadStateChange();
            this.setCommentInfo();
            
            // 重新初始化相关组件
            this.initCodeHighlight(false);
            this.lazyLoadInit();
            this.tooltipInit();
            
            // 重新绑定事件
            this.eventCommentPageChangeEvent();
            this.eventOpenCommentBox();
            this.eventCloseCommentBox();
            
            // 滚动到评论区域
            this.gotoArea("#comments");
        },
        error: (res) => {
            this.commentFormLoadStateChange();
            let msg = "评论提交失败";
            if (res.responseJSON && res.responseJSON.msg) {
                msg = res.responseJSON.msg;
            }
            this.toast(msg, TYPE_DANGER);
        }
    });
}

    commentFormLoadStateChange() {
        const commentSubmit = $("#comment-submit");
        if (this.data.comment.loading) {
            commentSubmit.html("请等待" + this.data.comment.time + "s");
            this.data.comment.val = setInterval(() => {
                if (this.data.comment.time <= 1) {
                    clearInterval(this.data.comment.val);
                    commentSubmit.html("提交评论");
                    commentSubmit.removeAttr("disabled");
                    this.data.comment.time = 5;
                } else {
                    --this.data.comment.time;
                    commentSubmit.html("请等待" + this.data.comment.time + "s");
                }
            }, 1000);
        } else {
            commentSubmit.html('<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>提交中...');
            commentSubmit.attr("disabled", true)
        }
        this.data.comment.loading = !this.data.comment.loading;
    }

    eventOpenCommentBox() {
        $(document).off("click", ".comment-reply");
        $(document).on("click", ".comment-reply", function(e) {
            e.preventDefault();
            const replyBtn = $(e.currentTarget);
            const replyId = replyBtn.attr("data-coid");
            if ($.trim(replyId) === '') {
                window.Puock.toast('结构有误', TYPE_DANGER);
                return;
            }
            const cf = $("#comment-form");
            const commentLi = replyBtn.closest('.post-comment');
            // 只在表单在原位时插入占位符
            if (!$("#comment-form-place-holder").length && cf.parent().attr("id") === "comment-form-box") {
                cf.before('<div id="comment-form-place-holder"></div>');
            }
            // 每次都append到目标评论下方
            commentLi.append(cf);
            $("#comment-cancel").removeClass("d-none");
            $("#comment").val("");
            $("#comment_parent").val(replyId);
            window.Puock.data.comment.replyId = replyId;
            // 滚动至表单
            if (cf.length && cf[0].scrollIntoView) {
                cf[0].scrollIntoView({behavior: "smooth", block: "center"});
            }
        });
    }

    eventCloseCommentBox() {
        $(document).off("click", "#comment-cancel");
        $(document).on("click", "#comment-cancel", () => {
            const cf = $("#comment-form");
            const holder = $("#comment-form-place-holder");
            if (holder.length) {
                holder.before(cf);
                holder.remove();
            } else {
                $("#comment-form-box").append(cf);
            }
            $("#comment-cancel").addClass("d-none");
            this.data.comment.replyId = null;
            $("#comment_parent").val('');
        });
    }

    eventSendPostLike() {
    let lastSendTime = 0;
    let throttleTimeMs = 3000;
    $(document).on("click", "#post-like", (e) => {
        const currentTime = new Date().getTime();
        if (currentTime - lastSendTime < throttleTimeMs) {
            this.toast("操作过于频繁", TYPE_WARNING);
            return;
        }
        lastSendTime = currentTime;
        
        const vm = $(this.ct(e));
        let cid = vm.attr("data-id");
        
        // 发送 AJAX 请求到当前文章页面
        $.ajax({
            url: window.location.href,
            type: 'POST',
            data: {
                likeup: 1,
                cid: cid
            },
            dataType: 'json',
            success: (response) => {
                // 检查返回的数据格式并更新点赞数
                if (response.success) {
                    vm.find("span").html(response.likes);
                    vm.addClass("bg-primary text-light");
                    this.toast("点赞成功", TYPE_SUCCESS);
                } else {
                    this.toast(response.msg || "点赞失败", TYPE_WARNING);
                }
            },
            error: () => {
                this.toast('点赞异常', TYPE_DANGER);
            }
        });
    })
}

    eventSmiley() {
        $(document).off('click', '.smiley-img');
        $(document).on('click', '.smiley-img', (e) => {
            const comment = $("#comment");
            comment.val(comment.val() + ' ' + $(this.ct(e)).attr("data-id") + ' ');
            layer.closeAll();
        });
    }

    startLoading() {
        return layer.load(0, {
            shade: [0.5, '#000']
        })
    }

    stopLoading(id = null) {
        layer.close(id)
    }

    getRemoteHtmlNode(url, callback) {
        const loading = this.startLoading()
        $.ajax({
            url: url,
            type: 'GET',
            success: (res)=>{
                this.stopLoading(loading)
                callback(res)
            },
            error: (err)=> {
                console.error(err)
                this.stopLoading(loading)
                this.toast("获取内容节点数据失败", TYPE_DANGER)
            }
        })
    }

    initModalToggle() {
        $(document).on("click", ".pk-modal-toggle", (e) => {
            const el = $(this.ct(e));
            const noTitle = el.data("no-title") !== undefined;
            const noPadding = el.data("no-padding") !== undefined;
            const title = el.attr("title") || el.data("title") || '提示';
            const url = el.data("url");
            const onceLoad = el.data("once-load")
            const id = SparkMD5.hash(url)
            if (onceLoad && this.data.modalStorage[id]) {
                this.modalLoadRender(id, this.data.modalStorage[id], title, noTitle, noPadding)
            } else {
                this.getRemoteHtmlNode(url, (res) => {
                    if (onceLoad) {
                        if (!this.data.modalStorage[id]) {
                            this.data.modalStorage[id] = res;
                        }
                    }
                    this.modalLoadRender(id, res, title, noTitle, noPadding)
                })
            }
        })
    }

    modalLoadRender(dataId, html, title, noTitle, noPadding) {
        const id = "pk-modal-" + dataId;
        layer.open({
            type: 1,
            title: noTitle ? false : title,
            content: `<div id="${id}" style='${noPadding ? '' : 'padding: 20px'}' class='fs14'>${html}</div>`,
            shadeClose: true,
        })
        const idEl = $("#" + id);
        this.lazyLoadInit(idEl);
        this.tooltipInit(idEl.find("[data-bs-toggle=\"tooltip\"]"));
    }

    eventPostMainBoxResize() {
        $(document).on("click", ".post-main-size", () => {
            const postMain = $("#post-main"),
                postSlider = $("#sidebar"),
                min = postMain.hasClass("col-lg-8");
            postMain.removeClass(min ? "col-lg-8" : "col-lg-12");
            postMain.addClass(min ? "col-lg-12" : "col-lg-8");
            min ? postSlider.removeClass("d-lg-block") : postSlider.addClass("d-lg-block");
        })
    }

    katexParse() {
        return;
        if (typeof katex !== 'undefined') {
            const ks = $(document).find(".language-katex");
            const kl = $(document).find(".language-inline");
            console.log(ks, kl)
            if (ks.length > 0) {
                ks.parent("pre").attr("style", "text-align: center; background: none;");
                ks.addClass("katex-container").removeClass("language-katex");
                $(".katex-container").each((_, v) => {
                    this.katexItemParse($(v))
                });
            }
            if (kl.length > 0) {
                kl.each((_, v) => {
                    this.katexItemParse($(v))
                });
            }
        }
    }

    katexItemParse(item) {
        const katexText = item.text();
        const el = item.get(0);
        if (item.parent("code").length === 0) {
            try {
                katex.render(katexText, el)
            } catch (err) {
                item.html("<span class='err'>" + err)
            }
        }
    }

    initGithubCard() {
        $.each($(".github-card"), (index, _el) => {
            const el = $(_el);
            const repo = el.attr("data-repo");
            if (repo) {
                $.get(`https://api.github.com/repos/${repo}`, (res) => {
                    const link_html = `class="hide-hover" href="${res.html_url}" target="_blank" rel="noreferrer"`;
                    el.html(`<div class="card-header"><i class="fa-brands fa-github"></i><a ${link_html}>${res.full_name}</a></div>
                    <div class="card-body">${res.description}</div>
                    <div class="card-footer">
                    <div class="row">
                    <div class="col-4"><i class="fa-regular fa-star"></i><a ${link_html}>${res.stargazers_count}</a></div>
                    <div class="col-4"><i class="fa-solid fa-code-fork"></i><a ${link_html}>${res.forks}</a></div>
                    <div class="col-4"><i class="fa-regular fa-eye"></i><a ${link_html}>${res.subscribers_count}</a></div>
                    </div>
                    </div>
                `);
                    el.addClass("loaded");
                }, 'json').fail((err) => {
                    el.html(`<div class="alert alert-danger"><i class="fa fa-warning"></i>&nbsp;请求Github项目详情异常：${repo}</div>`)
                });
            }
        })
    }

    keyUpHandle() {
        const prevOrNextEl = $(".single-next-or-pre")
        if (prevOrNextEl) {
            window.onkeyup = function (event) {
                if('BODY'===event.target?.tagName){
                    let url = null;
                    switch (event.key) {
                        case 'ArrowLeft': {
                            url = prevOrNextEl.find("a[rel='prev']").attr("href");
                            break
                        }
                        case 'ArrowRight': {
                            url = prevOrNextEl.find("a[rel='next']").attr("href");
                            break
                        }
                    }
                    if (url) {
                        window.location = url
                    }
                }
            }
        }
    }

    swiperInit() {
        $("[data-swiper='init']").each((_, _el) => {
            const el = $(_el);
            const swiperClass = el.attr("data-swiper-class");
            const elArgs = el.attr("data-swiper-args");
            let args = {}
            if (elArgs) {
                args = JSON.parse(elArgs)
            }
            new Swiper('.' + swiperClass, args);
        });
    }

    swiperOnceEvent() {
        $(document).on("click", ".swiper-slide a", (e) => {
            if (this.data.params.is_pjax) {
                e.preventDefault();
                this.goUrl(e.currentTarget.href)
            }
        });
    }

    toast(msg, type = TYPE_PRIMARY, options = {}) {
        options = Object.assign({
            duration: 2600,
            close: false,
            position: 'right',
            gravity: 'bottom',
            offset: {},
            className: 't-' + type,
        }, options)
        const t = Toastify({
            text: msg,
            ...options
        });
        t.showToast();
        return t;
    }

    // 新增：统一初始化评论相关事件
    initCommentEvents() {
        this.eventOpenCommentBox();
        this.eventCloseCommentBox();
        this.eventSmiley();
    }
}

jQuery(() => {
        if (window.$ === undefined) {
            window.$ = jQuery;
        }
        window.Puock = new Puock()
        window.Puock.onceInit()
    }
)

