"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decideIgnoreFlags = decideIgnoreFlags;
const ot_layout_1 = require("@ot-builder/ot-layout");
function decideIgnoreFlags(gs, gdef) {
    if (!gdef || !gs || !gs.size)
        return null;
    const [nonMarks, marks] = gsSplitMarks(gs, gdef.glyphClassDef);
    const igfBase = igfGlyphClass(nonMarks, gdef.glyphClassDef, ot_layout_1.Gdef.GlyphClass.Base, { ignoreBaseGlyphs: true }, { ignoreBaseGlyphs: false });
    const igfLigature = igfGlyphClass(nonMarks, gdef.glyphClassDef, ot_layout_1.Gdef.GlyphClass.Ligature, { ignoreLigatures: true }, { ignoreLigatures: false });
    const igfMark = igfGlyphClass(marks, gdef.glyphClassDef, ot_layout_1.Gdef.GlyphClass.Mark, { ignoreMarks: true }, { ignoreMarks: false }) ||
        igfMarkAttachmentClass(marks, gdef.glyphClassDef, gdef.markAttachClassDef) ||
        igfMarkFilterSet(marks, gdef.glyphClassDef, gdef.markGlyphSets);
    return {
        ...igfBase,
        ...igfLigature,
        ...igfMark
    };
}
/// Split non-mark and mark glyphs
function gsSplitMarks(ignoredGlyphs, glyphClassDef) {
    if (!glyphClassDef)
        return [new Set(ignoredGlyphs), new Set()];
    const marks = new Set(), nonMarks = new Set();
    for (const g of ignoredGlyphs) {
        if (ot_layout_1.Gdef.GlyphClass.Mark === glyphClassDef.get(g)) {
            marks.add(g);
        }
        else {
            nonMarks.add(g);
        }
    }
    return [nonMarks, marks];
}
function igfGlyphClass(ignoredGlyphs, glyphClassDef, glyphClass, positive, negative) {
    if (!glyphClassDef)
        return null;
    let has = false, all = true;
    for (const [g, cl] of glyphClassDef) {
        if (cl !== glyphClass)
            continue;
        if (ignoredGlyphs.has(g)) {
            has = true;
        }
        else {
            all = false;
        }
    }
    if (!has) {
        return negative;
    }
    else if (all) {
        return positive;
    }
    else {
        return null;
    }
}
function igfMarkAttachmentClass(ignoredMarks, glyphClassDef, markAttachmentClassDef) {
    if (!glyphClassDef || !markAttachmentClassDef)
        return null;
    // We need to iterate through all the marks, since in some cases we are ignoring mark class "0"
    const keptMarkClasses = new Set();
    const ignoredMarkClasses = new Set();
    for (const [g, gc] of glyphClassDef) {
        if (gc !== ot_layout_1.Gdef.GlyphClass.Mark)
            continue;
        const k = markAttachmentClassDef.get(g) || 0;
        (ignoredMarks.has(g) ? ignoredMarkClasses : keptMarkClasses).add(k);
    }
    let finalMarkClass = undefined;
    for (const k of keptMarkClasses) {
        // Hybrid class, fail
        if (ignoredMarkClasses.has(k))
            return null;
        // Multiple mark classes to keep, fail
        if (finalMarkClass != undefined)
            return null;
        finalMarkClass = k;
    }
    // Nothing to keep, fail
    if (!finalMarkClass || finalMarkClass <= 0 || finalMarkClass > 0xff)
        return null;
    return { markAttachmentType: finalMarkClass };
}
function igfMarkFilterSet(ignoredMarks, glyphClassDef, markGlyphSets) {
    if (!glyphClassDef || !markGlyphSets)
        return null;
    out: for (let mgsIndex = 0; mgsIndex < markGlyphSets.length; mgsIndex++) {
        const mgs = markGlyphSets[mgsIndex];
        for (const [g, gc] of glyphClassDef) {
            if (gc !== ot_layout_1.Gdef.GlyphClass.Mark)
                continue;
            if (ignoredMarks.has(g) !== !mgs.has(g))
                continue out;
        }
        return { markFilteringSet: mgsIndex };
    }
    return null;
}
//# sourceMappingURL=decide-ignore-flags.js.map