"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.canPossiblyPreviewExtension = canPossiblyPreviewExtension;
exports.displayQuickPreviewWindow = displayQuickPreviewWindow;
exports.generatePreview = generatePreview;
const child_process_1 = require("child_process");
const path_1 = __importDefault(require("path"));
const electron_1 = require("electron");
async function generatePreviewToken(previewPath) {
    return electron_1.ipcRenderer.invoke('quickpreview:generateToken', previewPath);
}
function cleanupPreviewToken(token) {
    electron_1.ipcRenderer.invoke('quickpreview:cleanupToken', token);
}
const QuickPreviewCSP = [
    "default-src 'self'",
    "script-src 'self' 'unsafe-inline'",
    "style-src 'self' 'unsafe-inline'",
    "img-src 'self' data: https: http:",
    "object-src 'none'",
    "frame-src 'none'",
    "base-uri 'self'",
].join('; ');
let quickPreviewWindow = null;
let captureWindow = null;
let captureWindowInUse = false;
const captureQueue = [];
const filesRoot = __dirname.replace('app.asar', 'app.asar.unpacked');
const FileSizeLimit = 5 * 1024 * 1024;
const ThumbnailWidth = 320 * (11 / 8.5);
const QuicklookIsAvailable = process.platform === 'darwin';
const PDFJSRoot = path_1.default.join(filesRoot, 'pdfjs-4.3.136');
const QuicklookBlacklist = [
    'jpg',
    'bmp',
    'gif',
    'png',
    'jpeg',
    'zip',
    'tar',
    'gz',
    'bz2',
    'dmg',
    'exe',
    'ics',
];
const CrossplatformStrategies = {
    pdfjs: ['pdf'],
    mammoth: ['docx'],
    snarkdown: ['md'],
    xlsx: ['xls', 'xlsx', 'csv', 'eth', 'ods', 'fods', 'uos1', 'uos2', 'dbf', 'prn', 'xlw', 'xlsb'],
    prism: [
        'html',
        'svg',
        'xml',
        'css',
        'c',
        'cc',
        'cpp',
        'js',
        'jsx',
        'tsx',
        'ts',
        'go',
        'cs',
        'patch',
        'swift',
        'java',
        'json',
        'jsonp',
        'tex',
        'mm',
        'm',
        'h',
        'py',
        'rb',
        'rs',
        'sql',
        'yml',
        'yaml',
        'txt',
        'log',
    ],
};
const CrossplatformStrategiesBetterThanQuicklook = ['snarkdown', 'prism'];
function strategyForPreviewing(ext) {
    if (ext.startsWith('.'))
        ext = ext.substr(1);
    const strategy = Object.keys(CrossplatformStrategies).find((strategy) => CrossplatformStrategies[strategy].includes(ext));
    if (QuicklookIsAvailable && !QuicklookBlacklist.includes(ext)) {
        if (!strategy || !CrossplatformStrategiesBetterThanQuicklook.includes(strategy)) {
            return 'quicklook';
        }
    }
    return strategy;
}
const PreviewWindowMenuTemplate = [
    {
        label: 'File',
        role: 'window',
        submenu: [
            {
                label: 'Minimize Window',
                accelerator: 'CmdOrCtrl+M',
                role: 'minimize',
            },
            {
                label: 'Close Window',
                accelerator: 'CmdOrCtrl+W',
                role: 'close',
            },
        ],
    },
    {
        label: 'Edit',
        submenu: [
            {
                label: 'Undo',
                accelerator: 'CmdOrCtrl+Z',
                role: 'undo',
            },
            {
                label: 'Redo',
                accelerator: 'Shift+CmdOrCtrl+Z',
                role: 'redo',
            },
            {
                type: 'separator',
            },
            {
                label: 'Cut',
                accelerator: 'CmdOrCtrl+X',
                role: 'cut',
            },
            {
                label: 'Copy',
                accelerator: 'CmdOrCtrl+C',
                role: 'copy',
            },
            {
                label: 'Paste',
                accelerator: 'CmdOrCtrl+V',
                role: 'paste',
            },
            {
                label: 'Select All',
                accelerator: 'CmdOrCtrl+A',
                role: 'selectAll',
            },
        ],
    },
    {
        label: 'View',
        submenu: [
            {
                label: 'Reload',
                accelerator: 'CmdOrCtrl+R',
                click: function (item, focusedWindow) {
                    if (focusedWindow)
                        focusedWindow.reload();
                },
            },
            {
                label: 'Toggle Full Screen',
                accelerator: (function () {
                    if (process.platform === 'darwin')
                        return 'Ctrl+Command+F';
                    else
                        return 'F11';
                })(),
                click: function (item, focusedWindow) {
                    if (focusedWindow)
                        focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
                },
            },
            {
                label: 'Toggle Developer Tools',
                accelerator: (function () {
                    if (process.platform === 'darwin')
                        return 'Alt+Command+I';
                    else
                        return 'Ctrl+Shift+I';
                })(),
                click: function (item, focusedWindow) {
                    if (focusedWindow)
                        focusedWindow.webContents.toggleDevTools();
                },
            },
        ],
    },
];
function canPossiblyPreviewExtension(file) {
    if (file.size > FileSizeLimit) {
        return false;
    }
    return !!strategyForPreviewing(file.displayExtension());
}
function displayQuickPreviewWindow(filePath) {
    const isPDF = filePath.endsWith('.pdf');
    const strategy = strategyForPreviewing(path_1.default.extname(filePath));
    if (strategy === 'quicklook') {
        const currentWin = AppEnv.getCurrentWindow();
        currentWin.previewFile(filePath);
        return;
    }
    if (quickPreviewWindow === null) {
        const { BrowserWindow } = require('@electron/remote');
        quickPreviewWindow = new BrowserWindow({
            width: 800,
            height: 600,
            center: true,
            skipTaskbar: true,
            backgroundColor: isPDF ? '#404040' : '#FFF',
            webPreferences: {
                preload: path_1.default.join(filesRoot, 'preload.js'),
                nodeIntegration: false,
                contextIsolation: true,
            },
        });
        quickPreviewWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => {
            callback({
                responseHeaders: {
                    ...details.responseHeaders,
                    'Content-Security-Policy': [QuickPreviewCSP],
                },
            });
        });
        quickPreviewWindow.once('closed', () => {
            quickPreviewWindow = null;
        });
        quickPreviewWindow.setMenu(require('@electron/remote').Menu.buildFromTemplate(PreviewWindowMenuTemplate));
    }
    else {
        quickPreviewWindow.show();
    }
    quickPreviewWindow.setTitle(path_1.default.basename(filePath));
    const onLoadError = (err) => {
        if (!err?.message?.includes('ERR_ABORTED')) {
            console.error('Quickpreview display window failed to load:', err);
        }
    };
    if (isPDF) {
        quickPreviewWindow
            .loadFile(path_1.default.join(PDFJSRoot, 'web/viewer.html'), {
            search: `file=${encodeURIComponent(`file://${filePath}`)}`,
        })
            .catch(onLoadError);
    }
    else {
        quickPreviewWindow
            .loadFile(path_1.default.join(filesRoot, 'renderer.html'), {
            search: JSON.stringify({ mode: 'display', filePath, strategy }),
        })
            .catch(onLoadError);
    }
}
async function generatePreview({ file, filePath, previewPath, }) {
    const strategy = strategyForPreviewing(file.displayExtension());
    if (strategy === 'quicklook') {
        return await _generateQuicklookPreview({ filePath });
    }
    else if (strategy) {
        return await _generateCrossplatformPreview({ file, filePath, previewPath, strategy });
    }
    else {
        return false;
    }
}
async function _generateCrossplatformPreview({ file, filePath, previewPath, strategy, }) {
    return new Promise((resolve) => {
        captureQueue.push({ file, filePath, previewPath, strategy, resolve });
        if (!captureWindow || captureWindow.isDestroyed()) {
            captureWindow = _createCaptureWindow();
            _generateNextCrossplatformPreview();
        }
    });
}
function _createCaptureWindow() {
    const { BrowserWindow } = require('@electron/remote');
    const win = new BrowserWindow({
        width: ThumbnailWidth,
        height: ThumbnailWidth,
        show: false,
        webPreferences: {
            preload: path_1.default.join(filesRoot, 'preload.js'),
            nodeIntegration: false,
            contextIsolation: true,
        },
    });
    win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
        callback({
            responseHeaders: {
                ...details.responseHeaders,
                'Content-Security-Policy': [QuickPreviewCSP],
            },
        });
    });
    win.webContents.on('render-process-gone', (event, details) => {
        console.warn(`Thumbnail generation webcontents crashed (reason: ${details.reason}).`);
        if (captureWindow === win)
            captureWindow = null;
        win.destroy();
    });
    win.once('closed', () => {
        if (captureWindow === win)
            captureWindow = null;
    });
    return win;
}
async function _generateNextCrossplatformPreview() {
    if (captureQueue.length === 0) {
        if (!captureWindowInUse) {
            if (captureWindow && !captureWindow.isDestroyed()) {
                captureWindow.destroy();
            }
            else {
                console.warn(`Thumbnail generation finished but window is already destroyed.`);
            }
            captureWindow = null;
        }
        return;
    }
    const { strategy, filePath, previewPath, resolve } = captureQueue.pop();
    captureWindowInUse = true;
    let previewToken;
    try {
        previewToken = await generatePreviewToken(previewPath);
    }
    catch (err) {
        console.error('Quickpreview failed to generate token:', err);
        captureWindowInUse = false;
        process.nextTick(_generateNextCrossplatformPreview);
        resolve(false);
        return;
    }
    if (!captureWindow || captureWindow.isDestroyed()) {
        captureWindow = _createCaptureWindow();
    }
    captureWindow
        .loadFile(path_1.default.join(filesRoot, 'renderer.html'), {
        search: JSON.stringify({ strategy, mode: 'capture', filePath, previewToken }),
    })
        .catch((err) => {
        if (!err?.message?.includes('ERR_ABORTED')) {
            console.error('Quickpreview capture window failed to load:', err);
        }
    });
    let onFinalize = null;
    const timer = setTimeout(() => {
        console.warn(`Thumbnail generation timed out for ${filePath}`);
        onFinalize(false);
    }, 5000);
    const onRendererSuccess = () => {
        onFinalize(true);
    };
    onFinalize = (success) => {
        captureWindowInUse = false;
        clearTimeout(timer);
        if (captureWindow) {
            captureWindow.removeListener('page-title-updated', onRendererSuccess);
        }
        if (!success) {
            cleanupPreviewToken(previewToken);
        }
        process.nextTick(_generateNextCrossplatformPreview);
        resolve(success);
    };
    captureWindow.once('page-title-updated', onRendererSuccess);
}
async function _generateQuicklookPreview({ filePath }) {
    const dirQuoted = path_1.default.dirname(filePath).replace(/"/g, '\\"');
    const pathQuoted = filePath.replace(/"/g, '\\"');
    return new Promise((resolve) => {
        const cmd = '/usr/bin/qlmanage';
        const args = [
            '-t',
            '-f',
            `${window.devicePixelRatio}`,
            '-s',
            `${ThumbnailWidth}`,
            '-o',
            dirQuoted,
            pathQuoted,
        ];
        (0, child_process_1.execFile)(cmd, args, (error, stdout, stderr) => {
            if (error ||
                stdout.match(/No thumbnail created/i) ||
                (stderr && !stdout.includes('produced one thumbnail'))) {
                resolve(false);
            }
            else {
                resolve(true);
            }
        });
    });
}
//# sourceMappingURL=index.js.map