"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cliMain = cliMain;
const tslib_1 = require("tslib");
const Fs = tslib_1.__importStar(require("node:fs"));
const cli_shared_1 = require("@ot-builder/cli-shared");
const ot_builder_1 = require("ot-builder");
const arg_parser_1 = require("./arg-parser");
const create_ttc_1 = require("./glyph-sharing/create-ttc");
const sparse_sharer_1 = require("./glyph-sharing/sparse-sharer");
async function cliMain(argv) {
    const args = new arg_parser_1.ArgParser();
    for (const arg of argv.slice(2))
        args.arg(arg);
    if (args.displayHelp)
        return await (0, arg_parser_1.displayHelp)();
    if (args.displayVersion)
        return await (0, arg_parser_1.displayVersion)();
    if (!args.inputs.length) {
        throw new Error("Please specify at least one input font. Exit.");
    }
    if (!args.output) {
        throw new Error("Please specify an output. Exit");
    }
    if (!args.unify && !args.sparse) {
        await simpleMerging(args);
    }
    else {
        await glyphSharingMerging(args);
    }
}
async function simpleMerging(args) {
    const sfntList = [];
    for (const input of args.inputs) {
        if (args.verbose)
            process.stderr.write(`Processing ${input}\n`);
        const bufFont = await Fs.promises.readFile(input);
        if (bufFont.readUInt32BE(0) === tagToUInt32("ttcf")) {
            const ttc = ot_builder_1.FontIo.readSfntTtc(bufFont);
            for (const sub of ttc)
                sfntList.push(sub);
        }
        else {
            sfntList.push(ot_builder_1.FontIo.readSfntOtf(bufFont));
        }
    }
    if (args.verbose)
        process.stderr.write(`${sfntList.length} sub-fonts found.\n`);
    if (args.output) {
        const bufTtc = ot_builder_1.FontIo.writeSfntTtc(sfntList);
        await Fs.promises.writeFile(args.output, bufTtc);
    }
}
async function glyphSharingMerging(args) {
    const gsf = ot_builder_1.Ot.ListGlyphStoreFactory;
    const sharer = new sparse_sharer_1.SparseGlyphSharer(gsf);
    for (const input of args.inputs) {
        if (args.verbose)
            process.stderr.write(`Processing ${input}\n`);
        const bufFont = await Fs.promises.readFile(input);
        if (bufFont.readUInt32BE(0) === tagToUInt32("ttcf")) {
            const ttc = ot_builder_1.FontIo.readSfntTtc(bufFont);
            for (const sub of ttc) {
                const subFont = ot_builder_1.FontIo.readFont(sub, gsf);
                sharer.addFont(subFont);
            }
        }
        else {
            const subFont = ot_builder_1.FontIo.readFont(ot_builder_1.FontIo.readSfntOtf(bufFont), gsf);
            sharer.addFont(subFont);
        }
    }
    if (args.verbose)
        process.stderr.write(`${sharer.fonts.length} sub-fonts found.\n`);
    let sharing = null;
    if (args.sparse) {
        sharing = sharer.sparseSharing(sharer.fonts[0].head.unitsPerEm, sharer.fonts[0].head.unitsPerEm);
    }
    else {
        sharer.unifyGlyphList();
    }
    if (args.output) {
        const resultBuffers = [];
        for (const [iFont, font] of sharer.fonts.entries()) {
            const fur = sharer.fontUnificationResults[iFont];
            if (!args.sparse)
                renameGlyphs(iFont, font, fur);
            const cfg = (0, cli_shared_1.inferSaveCfg)(args, font);
            cfg.ttf = {
                ...cfg.ttf,
                gvarForceProduceGVD: args.sparse,
                gvarForceZeroGapsBetweenGVD: args.sparse
            };
            resultBuffers.push(ot_builder_1.FontIo.writeSfntOtf(ot_builder_1.FontIo.writeFont(font, cfg)));
        }
        const slices = (0, create_ttc_1.createTtcSlices)(resultBuffers, sharing);
        await Fs.promises.writeFile(args.output, ot_builder_1.FontIo.writeSfntTtcFromTableSlices(slices));
    }
}
function renameGlyphs(iFont, font, ur) {
    const gOrd = font.glyphs.decideOrder();
    const conflictSet = new Set();
    // Delete all glyph names
    for (const [gid, g] of gOrd.entries())
        g.name = undefined;
    // Populate "proper" names
    for (const [gid, g] of gOrd.entries()) {
        if (!gid) {
            nameGlyphWithoutConflict(g, ".notdef", conflictSet);
        }
        else {
            const urName = ur.originalNames.get(g);
            if (urName)
                nameGlyphWithoutConflict(g, urName, conflictSet);
        }
    }
    // Populate name for unused glyphs
    for (const [gid, g] of gOrd.entries()) {
        if (g.name)
            continue;
        nameGlyphWithoutConflict(g, `.unused${gid}`, conflictSet);
    }
}
function nameGlyphWithoutConflict(g, desired, conflictSet) {
    if (!conflictSet.has(desired)) {
        g.name = desired;
        conflictSet.add(desired);
        return;
    }
    for (let n = 2;; n++) {
        const nameT = desired + "." + n;
        if (!conflictSet.has(nameT)) {
            g.name = nameT;
            conflictSet.add(nameT);
            return;
        }
    }
}
function tagToUInt32(x) {
    return ((x.charCodeAt(0) & 0xff) * 256 * 256 * 256
        + (x.charCodeAt(1) & 0xff) * 256 * 256
        + (x.charCodeAt(2) & 0xff) * 256
        + (x.charCodeAt(3) & 0xff));
}
//# sourceMappingURL=index.js.map