// Lightweight polyfills for older Chromium (e.g., Electron 13 / Chrome 91)
// Keep this file minimal and synchronous, it runs before page scripts in webview.

; (function () {
    try {
        // Array.prototype.at
        if (!Array.prototype.at) {
            Object.defineProperty(Array.prototype, 'at', {
                value: function at(n) {
                    n = Math.trunc(n) || 0
                    if (n < 0) n += this.length
                    if (n < 0 || n >= this.length) return undefined
                    return this[n]
                },
                writable: true,
                configurable: true,
            })
        }

        // Object.hasOwn
        if (!Object.hasOwn) {
            Object.hasOwn = function (obj, prop) {
                return Object.prototype.hasOwnProperty.call(obj, prop)
            }
        }

        // Array.prototype.findLast / findLastIndex
        if (!Array.prototype.findLast) {
            Object.defineProperty(Array.prototype, 'findLast', {
                value: function (predicate, thisArg) {
                    if (this == null) throw new TypeError('Array.prototype.findLast called on null or undefined')
                    if (typeof predicate !== 'function') throw new TypeError('predicate must be a function')
                    const o = Object(this)
                    const len = o.length >>> 0
                    for (let i = len - 1; i >= 0; i--) {
                        const kValue = o[i]
                        if (predicate.call(thisArg, kValue, i, o)) return kValue
                    }
                    return undefined
                },
            })
        }
        if (!Array.prototype.findLastIndex) {
            Object.defineProperty(Array.prototype, 'findLastIndex', {
                value: function (predicate, thisArg) {
                    if (this == null) throw new TypeError('Array.prototype.findLastIndex called on null or undefined')
                    if (typeof predicate !== 'function') throw new TypeError('predicate must be a function')
                    const o = Object(this)
                    const len = o.length >>> 0
                    for (let i = len - 1; i >= 0; i--) {
                        const kValue = o[i]
                        if (predicate.call(thisArg, kValue, i, o)) return i
                    }
                    return -1
                },
            })
        }

        // URL.canParse
        if (!('canParse' in URL)) {
            URL.canParse = function (url, base) {
                try {
                    // eslint-disable-next-line no-new
                    new URL(url, base)
                    return true
                } catch (e) {
                    return false
                }
            }
        }

        // structuredClone (best-effort; not covering complex cases like functions, DOM nodes, etc.)
        if (typeof globalThis.structuredClone !== 'function') {
            globalThis.structuredClone = function (value) {
                // Handle simple cases safely
                if (value == null || typeof value !== 'object') return value
                // Date
                if (value instanceof Date) return new Date(value.getTime())
                // RegExp
                if (value instanceof RegExp) return new RegExp(value.source, value.flags)
                // ArrayBuffer / TypedArrays
                if (value instanceof ArrayBuffer) return value.slice(0)
                if (ArrayBuffer.isView(value)) return new value.constructor(value)
                // Fallback JSON clone for plain data
                try {
                    return JSON.parse(JSON.stringify(value))
                } catch (e) {
                    // As last resort, shallow clone
                    if (Array.isArray(value)) return value.slice()
                    return Object.assign({}, value)
                }
            }
        }

        // Element.replaceChildren
        if (!Element.prototype.replaceChildren) {
            Element.prototype.replaceChildren = function () {
                while (this.firstChild) this.removeChild(this.firstChild)
                if (arguments.length === 0) return
                this.append.apply(this, arguments)
            }
        }
    } catch (err) {
        // Avoid breaking host app due to polyfill errors
        // console.warn('polyfills init error:', err)
    }
})()


    // Electron IPC bridge and lightweight selection trigger for webview
    ; (function () {
        try {
            // 在 preload 中 Node 可用；部分站点需要与 Electron 通信，但开启 nodeIntegration 会引发 UMD 走 CJS 分支（ev-emitter 等 require 报错）
            // 这里做最小“CJS 沙箱”：仅放行 require('electron')，屏蔽 module/exports，避免第三方 CDN 误以为是完整 Node 环境
            let electronModule = null;
            try { electronModule = require('electron'); } catch (_) { }
            const { ipcRenderer } = electronModule || {};

            if (typeof window !== 'undefined') {
                // 仅允许 require('electron')
                try {
                    const originalRequire = (typeof require === 'function') ? require : null;
                    Object.defineProperty(window, 'require', {
                        configurable: true,
                        enumerable: false,
                        writable: true,
                        value: function (name) {
                            if (name === 'electron' && originalRequire) return originalRequire('electron');
                            // 其它模块一律阻断，促使 UMD 走浏览器分支
                            throw new Error('[sandbox] require("' + name + '") is blocked in webview');
                        }
                    });
                } catch (_) { }
                try { window.module = undefined; } catch (_) { }
                try { window.exports = undefined; } catch (_) { }
            }

            // Expose global bridge for site scripts (backward-compatible with older integration)
            if (!globalThis.ipc2electronTranslate) {
                globalThis.ipc2electronTranslate = function (info) {
                    try {
                        ipcRenderer.sendToHost('clientTranslate', info);
                    } catch (_) { }
                }
            }
            if (!globalThis.ipc2electronTranslateClose) {
                globalThis.ipc2electronTranslateClose = function () {
                    try {
                        ipcRenderer.sendToHost('clientTranslateClose');
                    } catch (_) { }
                }
            }

            // Optional: auto trigger on text selection for qinyan files page (best-effort)
            // This is conservative to avoid spam; the site can still call ipc2electronTranslate directly
            (function setupSelectionHook() {
                try {
                    const href = String(location && location.href || '');
                    // 在资源详情页或内置 PDF 预览页生效
                    if (!(/\/files\//.test(href) || /\/pdf-fox\//.test(href))) return;

                    let lastText = '';
                    let lastTs = 0;
                    const throttleMs = 600;

                    function pickTextFrom(doc) {
                        try {
                            const w = (doc && doc.defaultView) || window;
                            const sel = (doc && doc.getSelection ? doc.getSelection() : (w.getSelection && w.getSelection())) || null;
                            const text = sel ? String(sel.toString() || '').trim() : '';
                            const now = Date.now();
                            if (!text) return;
                            if (text === lastText && (now - lastTs) < 2000) return;
                            lastText = text; lastTs = now;
                            globalThis.ipc2electronTranslate && globalThis.ipc2electronTranslate({ content: text });
                        } catch (_) { }
                    }

                    function makeThrottledPick(doc) {
                        return function () {
                            const now = Date.now();
                            if ((now - lastTs) < throttleMs) return;
                            pickTextFrom(doc);
                        }
                    }

                    const throttledPickTop = makeThrottledPick(document);

                    // 顶层页面监听
                    window.addEventListener('mouseup', throttledPickTop, true);
                    window.addEventListener('keyup', (e) => {
                        // Trigger on common select-all or navigation in selection
                        if (e && (e.key === 'Shift' || e.key === 'Control' || e.key === 'Meta' || e.key === 'Alt')) return;
                        throttledPickTop();
                    }, true);

                    // 监听同源 iframe（如 /pdf-fox/ 的 #J_iframe）里的选择
                    function attachFrameListeners(frame) {
                        try {
                            const doc = frame && (frame.contentDocument || (frame.contentWindow && frame.contentWindow.document));
                            if (!doc) return;
                            const throttledPickFrame = makeThrottledPick(doc);
                            doc.addEventListener('mouseup', throttledPickFrame, true);
                            doc.addEventListener('keyup', (e) => {
                                if (e && (e.key === 'Shift' || e.key === 'Control' || e.key === 'Meta' || e.key === 'Alt')) return;
                                throttledPickFrame();
                            }, true);
                        } catch (_) { }
                    }

                    Array.prototype.forEach.call(document.querySelectorAll('iframe'), attachFrameListeners);

                    const mo = new MutationObserver((mutations) => {
                        mutations.forEach((m) => {
                            Array.prototype.forEach.call(m.addedNodes || [], (node) => {
                                if (node && node.tagName === 'IFRAME') attachFrameListeners(node);
                            });
                        });
                    });
                    try { mo.observe(document.documentElement, { childList: true, subtree: true }); } catch (_) { }
                } catch (_) { }
            })();
        } catch (err) {
            // Silent guard
        }
    })();


