/**
 * @author j433866 [j433866@gmail.com]
 * @copyright Crown Copyright 2018
 * @license Apache-2.0
 */

import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import qr from "qr-image";
import { toBase64 } from "../lib/Base64";
import { isImage } from "../lib/FileType";
import Utils from "../Utils";

/**
 * Generate QR Code operation
 */
class GenerateQRCode extends Operation {

    /**
     * GenerateQRCode constructor
     */
    constructor() {
        super();

        this.name = "Generate QR Code";
        this.module = "Image";
        this.description = "Generates a Quick Response (QR) code from the input text.<br><br>A QR code is a type of matrix barcode (or two-dimensional barcode) first designed in 1994 for the automotive industry in Japan. A barcode is a machine-readable optical label that contains information about the item to which it is attached.";
        this.infoURL = "https://wikipedia.org/wiki/QR_code";
        this.inputType = "string";
        this.outputType = "byteArray";
        this.presentType = "html";
        this.args = [
            {
                "name": "Image Format",
                "type": "option",
                "value": ["PNG", "SVG", "EPS", "PDF"]
            },
            {
                "name": "Module size (px)",
                "type": "number",
                "value": 5
            },
            {
                "name": "Margin (num modules)",
                "type": "number",
                "value": 2
            },
            {
                "name": "Error correction",
                "type": "option",
                "value": ["Low", "Medium", "Quartile", "High"],
                "defaultIndex": 1
            }
        ];
    }

    /**
     * @param {string} input
     * @param {Object[]} args
     * @returns {byteArray}
     */
    run(input, args) {
        const [format, size, margin, errorCorrection] = args;

        // Create new QR image from the input data, and convert it to a buffer
        const qrImage = qr.imageSync(input, {
            type: format,
            size: size,
            margin: margin,
            "ec_level": errorCorrection.charAt(0).toUpperCase()
        });

        if (qrImage == null) {
            throw new OperationError("Error generating QR code.");
        }

        switch (format) {
            case "SVG":
            case "EPS":
            case "PDF":
                return [...Buffer.from(qrImage)];
            case "PNG":
                // Return the QR image buffer as a byte array
                return [...qrImage];
            default:
                throw new OperationError("Unsupported QR code format.");
        }
    }

    /**
     * Displays the QR image using HTML for web apps
     *
     * @param {byteArray} data
     * @returns {html}
     */
    present(data, args) {
        if (!data.length) return "";

        const [format] = args;

        if (format === "PNG") {
            let dataURI = "data:";
            const mime = isImage(data);
            if (mime){
                dataURI += mime + ";";
            } else {
                throw new OperationError("Invalid PNG file generated by QR image");
            }
            dataURI += "base64," + toBase64(data);

            return `<img src="${dataURI}">`;
        }

        return Utils.byteArrayToChars(data);
    }

}

export default GenerateQRCode;
