
const fs = require("fs"),
    path = require("path"),
    Document = require("./document.js").Document;
    DbDoc = require("./sequelize.js").Document;
    DbDocCover = require("./sequelize.js").DocumentCover;
    CONFIG = require("../config.js");

function CreateDocument(filename, stat) {
    var doc = new Document(filename, stat);
    if (!doc.handler) {
        console.error("Unknown file type: " +doc.name);
        return null;
    }
    return doc;
}

function consumeDir(dirs, files) {
    (fs.readdirSync(dirs[0]) || []).forEach(shortname => {
        var fileName = path.join(dirs[0], shortname),
            stat = fs.statSync(fileName);

        if (stat.isDirectory()) {
            dirs.push(fileName);
        } else {
            var doc = CreateDocument(fileName, stat);
            if (doc)
                files.push(doc);
        }
    });
    dirs.splice(0, 1);
}

function FilePool(files) {
    this.files = files;
}

FilePool.prototype.createDbDocument = async function(hash) {
    var file = this.files[hash],
        meta = [];

    meta = await Promise.all([
        file.getPageCount(),
        file.getCover(),
    ]);
    return DbDoc.create({
        id: hash,
        path: file.path,
        title: null,
        author: null,
        pageCount: meta[0],
        isbn: null,
        fileSize: file.size
    }).then(() => DbDocCover.create({
        id: hash,
        cover: meta[1]
    }));
}

FilePool.prototype.sync = function(dbIds) {
    var toAdd = [],
        toRm = [];

    for (var i in this.files) {
        if (!dbIds[i]) {
            // new file !
            toAdd.push(i);
        } else if (dbIds[i] !== this.files[i].path) {
            // File Moved !
            toRm.push(i);
            toAdd.push(i);
        }
    }
    for (var i in dbIds) {
        if (!this.files[i]) {
            // file removed !
            toRm.push(i);
        }
    }

    var promises = [];
    toRm.length && promises.push(DbDocCover.destroy({ where: { id: toRm} }).then(DbDoc.destroy({ where: { id: toRm }})));
    toAdd.forEach(i => promises.push(this.createDbDocument(i)));
    return Promise.all(promises);
};

async function CreateFilePool() {
    var files = [],
        dirs = CONFIG.directories.slice(0);

    while (dirs.length)
        consumeDir(dirs, files);
    const results = await Promise.all(files.map(i => i.computeMd5Async()))
    filesByHash = {};
    files.forEach(i => filesByHash[i.hash] = i);
    return new FilePool(filesByHash);
}

function refreshFiles() {
    CreateFilePool().then(pool => {
        var dbIds = DbDoc.findAll({ attributes: [ "id", "path" ] }).then(async dbIds => {
            var ids = {};
            dbIds.forEach(i => ids[i.id] = i.path);
            await pool.sync(ids);
            console.log("Done");
        });
    });
};

refreshFiles();
setInterval(refreshFiles, CONFIG.scanInterval * 60 * 1000);

