Source: models/core/pdf.js

const pdf = require('pdfjs');
const fs = require('fs');
const EventEmitter = require('events');

/**
 * Class for generic PDF document creation
 * @author Jens Dinstühler
 * @class 
 */
class Pdf extends EventEmitter {

    /**
     * @constructor
     * @param {object} aLogger 
     */
    constructor(aLogger) {
        super();
        this.headerTitle = 'ALARMiator';
        this.headerLogo = global.appRoot + '/public/assets/img/logoPdf.jpg';
        this.headerLogoHeight = 25;
    }
    
    /**
     * initializes new pdf document
     */
    initialize() {
        this.doc = new pdf.Document({
            padding: 1 * pdf.cm
        })
    }

    /**
     * Adds document header
     */
    addHeader(title, padBottom = 3, withUrl = true) {
        // Add header
        const src = fs.readFileSync(this.headerLogo);
        const img = new pdf.Image(src);
        var header = this.doc.header().table({ widths: [null, null], paddingBottom: padBottom * pdf.cm }).row()
        header.cell().image(img, { height: this.headerLogoHeight })
        if (withUrl === true) {
            header.cell().text({ textAlign: 'right' })
                .add(this.headerTitle)
                .add('https://www.alarmiator.de', {
                    link: 'https://www.alarmiator.de',
                    underline: true,
                    color: 0x569cd6
                })
        } else {
            header.cell().text({ textAlign: 'right' })
                .add(this.headerTitle)
        }
        
    }

    /**
     * Adds document footer
     */
    addFooter() {
        // adds a footer
        this.doc.footer()
            .pageNumber(function (curr, total) { return curr + ' / ' + total }, { textAlign: 'center' })
    }

    /**
     * Adds the organization logo to the upper right corner of document
     * @param {string} imagePath 
     */
    setOrganizationLogo(imagePath) {
        const img = new pdf.Image(fs.readFileSync(imagePath))
        this.doc.image(img, {
            x: 0,
            y: 10,
            height: 25,
            align: 'right'
        })
    }

    /**
     * Adds a JPEG Image to document
     * @param {string} imagePath Path to jpeg image
     * @param {integer} xCoord x coordinate
     * @param {integer} yCoord y coordinate
     * @param {integer} heightValue height
     * @param {string} alignValue align
     */
    addImage(imagePath, xCoord, yCoord, heightValue, alignValue) {
        const src = fs.readFileSync(imagePath);
        const img = new pdf.Image(src)
        this.doc.image(img, {
            x: xCoord,
            y: yCoord,
            height: heightValue,
            align: alignValue
        })
    }

    /**
     * Writes file to disk
     * @param {string} filename 
     */
    writeDocToFile(filename, callback) {
        // Writes PDF Document
        var dest = fs.createWriteStream(filename);
        dest.on('finish', () => {
            return callback(true);
        });
        
        dest.on('error', (err) => {
            return callback(false);
        }) 
        //console.log('doc end');
        this.doc.end();
        //console.log('doc.pipe');
        this.doc.pipe(dest);
        //console.log('ende');
        // render something onto the document
        
    }

    /**
     * adds a new table to document
     * @param {array} colsWidthDefinition Array holding width of columns (e.g. [256, 256])
     * @param {integer} borderWidthValue border width
     */
    addTable(colsWidthDefinition, borderWidthValue, paddingValue = 5, borderColorValue = '0x000000', paddingBottomValue = 0) {
        this.table = this.doc.table({
            widths: colsWidthDefinition,
            borderWidth: borderWidthValue,
            borderColor: borderColorValue,
            paddingBottom: paddingBottomValue,
            padding: paddingValue
        })        
    }

    /**
     * 
     * @param {array} headerDefinition one dimensional array holding header title(s) as string
     */
    addTableHeader(headerDefinition) {
        var header = this.table.header()
        headerDefinition.forEach((aheader) => {
            header.cell(aheader, {
                backgroundColor: 0xC2C2C2,
                padding: 5
            });
        });
    }

    /**
     * adds another row to table
     * @param {array} rowsDefintion one dimensional array holding cell content as string
     */
    addTableRow(rowsDefintion, opts = []) {
        var row = this.table.row();
        rowsDefintion.forEach((arow, index) => {
            var opt = {};
            if ((opts.length) > index) {
                opt = opts[index];
                //console.log(opt);
            } else {
                opt = {};
            }
            row.cell(arow, opt);
        })
    }

    /**
     * adds text to the document
     * @param {string} text Text to add to document
     * @param {array} opts Array with options for text
     */
    addText(text, opts) {
        this.text = this.doc.text(text, opts);
    }

    /**
     * Adds a linebreak to an activr text block
     */
    addBr() {
        if (this.text != null) {
            this.text.br();
        }
    }

    async closePDF() {
        await this.doc.end()
    }
}

module.exports = Pdf;