import bytes from 'bytes';
import kink from '../shared/kink.js';
import { ChildProcessError, exec, spawn } from './process.js';
export const COMMAND_HANDLE = {
    ffmpeg: handleFfmpegCommand,
    black: handleBlackCommand,
    asmfmt: handleAsmfmtCommand,
    ktfmt: handleKtfmtCommand,
    convert: handleConvertCommand,
    pandoc: handlePandocCommand,
    java: handleJavaCommand,
    'clang++': handleClangppCommand,
    clang: handleClangCommand,
    llc: handleLlcCommand,
    'clang-format': handleClangFormatCommand,
    'swift-format': handleSwiftFormatCommand,
    swiftc: handleSwiftcCommand,
    fontforge: handleFontforgeCommand,
    mogrify: handleMogrifyCommand,
    '7z': handle7zCommand,
    inkscape: handleInkscapeCommand,
    unar: handleUnarCommand,
    rar: handleRarCommand,
    pdflatex: handlePdfLatexCommand,
    objdump: handleObjdumpCommand,
    rustc: handleRustcCommand,
    rustfmt: handleRustfmtCommand,
    rubocop: handleRubocopCommand,
    shfmt: handleShfmtCommand,
    zip: handleZipCommand,
    tar: handleTarCommand,
    exiftool: handleExiftoolCommand,
    'ebook-convert': handleEbookConvertCommand,
    soffice: handleSofficeCommand,
    jupyter: handleJupyterCommand,
    docx2pdf: handleDocx2pdfCommand,
    unoconv: handleUnoconvCommand,
};
export async function handleFfmpegCommand(cmd) {
    try {
        await spawn(cmd, msg => {
            const parsed = parseFfmpegError(msg.text);
            if (parsed) {
                console.log(parsed);
            }
        });
    }
    catch (e) {
        console.log(e);
        if (e instanceof Error) {
            if (e.message === 'Process error.') {
                throw e;
            }
        }
        throw e;
    }
}
export async function handleBlackCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleAsmfmtCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleKtfmtCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleConvertCommand(cmd) {
    try {
        return await exec(cmd.join(' '));
    }
    catch (e) {
        if (e instanceof ChildProcessError) {
            if (e.data.stderr) {
                if (e.data.stderr.match(/^convert: unable to open image/i)) {
                    // throw new Kink
                    throw new Error(`Cannot process image`);
                }
            }
        }
        else {
            throw new Error(`System error`);
        }
    }
}
export async function handlePandocCommand(cmd) {
    try {
        return await exec(cmd.join(' '));
    }
    catch (e) {
        if (e instanceof Error) {
            if (e instanceof ChildProcessError) {
                if (e.data.stderr?.match(/pandoc: (.+): withBinaryFile: does not exist \(No such file or directory\)/)) {
                    throw kink('file_missing_error', { path: RegExp.$1 });
                }
            }
        }
        throw e;
    }
}
export async function handleCommand(cmd) {
    const name = cmd[0];
    const handle = COMMAND_HANDLE[name];
    return await handle(cmd.list);
}
export async function handleJavaCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleClangppCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleClangCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleLlcCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleClangFormatCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleSwiftFormatCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleSwiftcCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleFontforgeCommand(cmd) {
    try {
        return await exec(cmd.join(' '));
    }
    catch (e) {
        if (e instanceof ChildProcessError) {
            if (e.data.stderr) {
                const parsedError = parseFontError(e.data.stderr);
                if (parsedError) {
                    throw kink('font_forge_error', { note: parsedError });
                }
            }
        }
        // throw e
    }
}
export async function handleMogrifyCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handle7zCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleInkscapeCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleUnarCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleRarCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleObjdumpCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleRustcCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleRustfmtCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleRubocopCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleShfmtCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleZipCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleTarCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleExiftoolCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleEbookConvertCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleSofficeCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleJupyterCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleDocx2pdfCommand(cmd) {
    return await exec(cmd.join(' '));
}
export async function handleUnoconvCommand(cmd) {
    return await exec(cmd.join(' '));
}
export function parseFontError(text) {
    const lines = text.trim().split(/\n/);
    if (!lines.shift()?.match(/^Copyright \(c\) 2000\-2023/)) {
        return;
    }
    let message = [];
    for (const line of lines) {
        if (line.startsWith(` `)) {
            continue;
        }
        if (line.trim().match(/^The requested file, (.+), does not exist$/)) {
            throw kink('file_missing_error', { path: RegExp.$1 });
        }
        else {
            message.push(line);
        }
    }
    return message.join('\n');
}
function parseFfmpegError(text) {
    const lines = text.split(/\n/);
    if (lines[0]?.match(/File '(?:.+)' already exists\. Exiting/)) {
        return { form: 'kink', text: `File already exists.` };
    }
    else if (lines[0]?.match(/^frame=\s*(.+)\s+fps=\s*(.+)\s+q=\s*(.+)\s+size=\s*(.+)\s+time=\s*(.+)\s+bitrate=\s*(.+)\s+speed=(.+)/)) {
        const { $1, $2, $3, $4, $5, $6, $7 } = RegExp;
        const frame = parseInt($1, 10);
        const fps = parseFloat($2);
        const q = parseFloat($3);
        const size = bytes($4);
        const [t, ms] = $5.split('.');
        const [h, m, s] = t.split(':');
        const totalSeconds = parseInt(s, 10) * 1000;
        const totalMinutes = parseInt(m, 10) * 60 * 1000;
        const totalHours = parseInt(h, 10) * 60 * 60 * 1000;
        const time = totalHours + totalMinutes + totalSeconds;
        const bitrate = bytes($6.split('bits/s').shift() + 'b');
        const speed = parseFloat($7);
        return {
            form: 'rise',
            link: {
                frame,
                fps,
                q,
                size,
                time,
                bitrate,
                speed,
            },
        };
    }
    else if (lines[0]?.match(/^frame=/)) {
        return;
    }
    else if (lines[0]?.match(/^Input #/)) {
        return;
    }
    return text;
}
// https://stackoverflow.com/questions/747982/can-ffmpeg-show-a-progress-bar
// https://www.npmjs.com/package/file-type
// https://github.com/apache/tika
export async function handlePdfLatexCommand(cmd) {
    try {
        await exec(cmd.join(' '));
    }
    catch (e) {
        if (e instanceof ChildProcessError) {
            const message = e.data.stdout && parseLatexError(e.data.stdout);
            const error = new Error(message ?? e.data.error.message);
            throw error;
        }
    }
}
function parseLatexError(text) {
    let lines = text.trim().split('\n');
    let firstErrorFound = false;
    let lastErrorFound = false;
    let message = [];
    let newLineCount = 0;
    lines.forEach(line => {
        if (line.match(/^\!/)) {
            if (firstErrorFound) {
                lastErrorFound = true;
            }
            firstErrorFound = true;
        }
        if (lastErrorFound) {
            return;
        }
        if (firstErrorFound) {
            // don't have more than 2 new lines in a row.
            if (line.match(/^\s*$/)) {
                newLineCount++;
                if (newLineCount > 1) {
                    return;
                }
            }
            else {
                newLineCount = 0;
            }
            if (line.match(/See the LaTeX manual/i)) {
                return;
            }
            if (line.match(/Type\s+H <return>\s+for immediate help/i)) {
                return;
            }
            if (line.match(/^\s+\.\.\.\s*/)) {
                return;
            }
            message.push(line.replace(/^\!\s+/, '').replace(/\s*$/, ''));
        }
    });
    return message.join('\n').replace(/\n\n+/gm, '\n\n');
}
//# sourceMappingURL=command.js.map