
const Handler = require("./documentHandler.js").DocumentHandler,
    assert = require("assert"),
    AdmZip = require("adm-zip"),
    Xml2js = require("xml2js"),
    Canvas = require("canvas"),
    fs = require("fs");

function EpubHandler(doc) {
    Handler.call(this, doc);
    this.data = null;
    this.loading = null;
}
EpubHandler.prototype = Object.create(Handler.prototype);

EpubHandler.prototype.parseFile = function() {
    return new Promise(async (res, rej) => {
        const zip = new AdmZip(this.doc.path),
            entries = zip.getEntries(),
            entriesByPath = {};
        entries.forEach(i => {
            entriesByPath[i.entryName] = i;
        });
        if (!entriesByPath["content.opf"])
            rej();
        Xml2js.parseString(entriesByPath["content.opf"].getData().toString("utf8"), ((err, result) => {
            if (err) {
                console.error("Malformed XML data in epub file", err);
                rej();
            }
            if (!result ||
                !result.package ||
                !result.package.manifest ||
                !result.package.manifest[0] ||
                !result.package.manifest[0].item ||
                !Array.isArray(result.package.manifest[0].item)) {
                console.error("Cannot read metadata epub file");
                rej();
            }
            this.data = {};
            for (var i =0, len = result.package.manifest[0].item.length;
                    i < len;
                    ++i) {
                var item = result.package.manifest[0].item[i]["$"];
                if (item && item.id === "cover") {
                    if (!entriesByPath[item.href]) {
                        console.error("Referenced file " +item.href +" not found");
                        continue;
                    }
                    this.data.cover = entriesByPath[item.href].getData();
                    break;
                }
            }
            if (!this.data.cover) {
                console.error("Cannot find cover");
                this.data = null;
                rej();
            }
            res(this.data);
        }).bind(this));
    });
}

EpubHandler.prototype.loadDocument = function() {
    return new Promise(((res, rej) => {
        if (this.data) {
            res(this.data);
        } else {
            if (this.loading)
                this.loading = this.loading.then((() => res(this.data)).bind(this));
            else
                this.loading = this.parseFile().then(doc => res(this.data));
        }
    }).bind(this));
}

EpubHandler.prototype.getPageCount = function() {
    return new Promise((res, rej) => res(null));
};

EpubHandler.prototype.getThumbmailViewport = function(fullWidth, fullHeight) {
    const maxSize = require("../config").thumbmailMaxSize;
    var ratio = Math.min(maxSize /fullHeight, maxSize /fullWidth);
    return {
        height: ratio *fullHeight,
        width: ratio *fullWidth
    };
};

EpubHandler.prototype.getCover = function() {
    return new Promise(async (res, rej) => {
        const data = await this.loadDocument(),
            image = new Canvas.Image();
        image.src = data.cover;
        const size = this.getThumbmailViewport(image.width, image.height),
            canvas = Canvas.createCanvas(size.width, size.height),
            ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0, size.width, size.height);
        canvas.toBuffer((err, buf) => res(buf), "image/png");
    });
};

EpubHandler.prototype.getPngPage = function(page, isThumbmail) {
    return new Promise((res, rej) => res(null));
};

module.exports.EpubHandler = EpubHandler;

