"use strict";
const sql = require('../../services/sql');
const html = require('html');
const tar = require('tar-stream');
const sanitize = require("sanitize-filename");
const repository = require("../../services/repository");
const utils = require('../../services/utils');
async function exportNote(req, res) {
    const noteId = req.params.noteId;
    const format = req.params.format;
    const branchId = await sql.getValue('SELECT branchId FROM branches WHERE noteId = ?', [noteId]);
    if (format === 'tar') {
        await exportToTar(branchId, res);
    }
    else if (format === 'opml') {
        await exportToOpml(branchId, res);
    }
    else {
        return [404, "Unrecognized export format " + format];
    }
}
function escapeXmlAttribute(text) {
    return text.replace(/&/g, '&')
        .replace(//g, '>')
        .replace(/"/g, '"')
        .replace(/'/g, ''');
}
function prepareText(text) {
    const newLines = text.replace(/(
]*>|
)/g, '\n')
                         .replace(/ /g, ' '); // nbsp isn't in XML standard (only HTML)
    const stripped = utils.stripTags(newLines);
    const escaped = escapeXmlAttribute(stripped);
    return escaped.replace(/\n/g, '
');
}
async function exportToOpml(branchId, res) {
    const branch = await repository.getBranch(branchId);
    const note = await branch.getNote();
    const title = (branch.prefix ? (branch.prefix + ' - ') : '') + note.title;
    const sanitizedTitle = sanitize(title);
    async function exportNoteInner(branchId) {
        const branch = await repository.getBranch(branchId);
        const note = await branch.getNote();
        const title = (branch.prefix ? (branch.prefix + ' - ') : '') + note.title;
        const preparedTitle = prepareText(title);
        const preparedContent = prepareText(note.content);
        res.write(`\n`);
        for (const child of await note.getChildBranches()) {
            await exportNoteInner(child.branchId);
        }
        res.write('');
    }
    res.setHeader('Content-Disposition', 'file; filename="' + sanitizedTitle + '.opml"');
    res.setHeader('Content-Type', 'text/x-opml');
    res.write(`
Trilium export
`);
    await exportNoteInner(branchId);
    res.write(`
`);
    res.end();
}
async function exportToTar(branchId, res) {
    const pack = tar.pack();
    const exportedNoteIds = [];
    const name = await exportNoteInner(branchId, '');
    async function exportNoteInner(branchId, directory) {
        const branch = await repository.getBranch(branchId);
        const note = await branch.getNote();
        const childFileName = directory + sanitize(note.title);
        if (exportedNoteIds.includes(note.noteId)) {
            saveMetadataFile(childFileName, {
                version: 1,
                clone: true,
                noteId: note.noteId,
                prefix: branch.prefix
            });
            return;
        }
        const metadata = {
            version: 1,
            clone: false,
            noteId: note.noteId,
            title: note.title,
            prefix: branch.prefix,
            type: note.type,
            mime: note.mime,
            attributes: (await note.getOwnedAttributes()).map(attribute => {
                return {
                    type: attribute.type,
                    name: attribute.name,
                    value: attribute.value,
                    isInheritable: attribute.isInheritable,
                    position: attribute.position
                };
            })
        };
        if (metadata.attributes.find(attributes => attributes.type === 'label' && attributes.name === 'excludeFromExport')) {
            return;
        }
        saveMetadataFile(childFileName, metadata);
        saveDataFile(childFileName, note);
        exportedNoteIds.push(note.noteId);
        for (const child of await note.getChildBranches()) {
            await exportNoteInner(child.branchId, childFileName + "/");
        }
        return childFileName;
    }
    function saveDataFile(childFileName, note) {
        const content = note.type === 'text' ? html.prettyPrint(note.content, {indent_size: 2}) : note.content;
        pack.entry({name: childFileName + ".dat", size: content.length}, content);
    }
    function saveMetadataFile(childFileName, metadata) {
        const metadataJson = JSON.stringify(metadata, null, '\t');
        pack.entry({name: childFileName + ".meta", size: metadataJson.length}, metadataJson);
    }
    pack.finalize();
    res.setHeader('Content-Disposition', 'file; filename="' + name + '.tar"');
    res.setHeader('Content-Type', 'application/tar');
    pack.pipe(res);
}
module.exports = {
    exportNote
};