"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GsubAlternateWriter = exports.GsubMultiWriter = exports.GsubAlternateReader = exports.GsubMultiReader = void 0;
const bin_util_1 = require("@ot-builder/bin-util");
const errors_1 = require("@ot-builder/errors");
const ot_layout_1 = require("@ot-builder/ot-layout");
const primitive_1 = require("@ot-builder/primitive");
const general_1 = require("../gsub-gpos-shared/general");
const coverage_1 = require("../shared/coverage");
const shared_types_1 = require("./shared-types");
const SubtableFormat1 = {
    read(view, lookup, ctx) {
        const format = view.uint16();
        errors_1.Assert.FormatSupported(`MultipleSubst / AlternateSubst`, format, 1);
        const cov = view.next(coverage_1.Ptr16GidCoverage);
        const count = view.uint16();
        errors_1.Assert.SizeMatch(`MultipleSubst / AlternateSubst count`, count, cov.length);
        for (const gid of cov) {
            const pSubst = view.ptr16();
            const substituteGlyphIDs = pSubst.next(shared_types_1.SimpleGidArray);
            lookup.mapping.set(ctx.gOrd.at(gid), substituteGlyphIDs.map(g => ctx.gOrd.at(g)));
        }
    },
    write(frag, mapping, ctx) {
        const { gidList, values } = coverage_1.CovUtils.splitListFromMap(mapping, ctx.gOrd);
        frag.uint16(1);
        frag.push(coverage_1.Ptr16GidCoverage, gidList, ctx.trick);
        frag.uint16(values.length);
        for (const to of values) {
            const fSeq = frag.ptr16New();
            fSeq.uint16(to.length);
            fSeq.array(primitive_1.UInt16, to.map(g => ctx.gOrd.reverse(g)));
        }
    }
};
class GsubMultiAlternateReaderBase {
    parseSubtable(view, lookup, context) {
        const format = view.lift(0).uint16();
        switch (format) {
            case 1:
                view.next(SubtableFormat1, lookup, context);
                break;
            default:
                throw errors_1.Errors.FormatNotSupported(`MultipleSubst / AlternateSubst`, format);
        }
    }
}
class State {
    constructor() {
        this.mapping = new Map();
        this.size = primitive_1.UInt16.size * 4;
    }
    tryAddMapping(from, to) {
        const deltaSize = primitive_1.UInt16.size * (1 + coverage_1.MaxCovItemWords + to.length);
        if (this.size + deltaSize > general_1.SubtableSizeLimit)
            return false;
        this.mapping.set(from, to);
        this.size += deltaSize;
        return true;
    }
}
class GsubMultiAlternateWriterBase {
    flush(frags, state, ctx) {
        if (!state.mapping.size)
            return;
        frags.push(bin_util_1.Frag.from(SubtableFormat1, state.mapping, ctx));
    }
    createSubtableFragments(lookup, ctx) {
        let state = new State();
        const frags = [];
        for (const [from, to] of lookup.mapping) {
            if (state.tryAddMapping(from, to))
                continue;
            this.flush(frags, state, ctx);
            state = new State();
            if (!state.tryAddMapping(from, to))
                throw errors_1.Errors.Unreachable();
        }
        this.flush(frags, state, ctx);
        return frags;
    }
}
class GsubMultiReader extends GsubMultiAlternateReaderBase {
    createLookup() {
        return new ot_layout_1.Gsub.Multiple();
    }
}
exports.GsubMultiReader = GsubMultiReader;
class GsubAlternateReader extends GsubMultiAlternateReaderBase {
    createLookup() {
        return new ot_layout_1.Gsub.Alternate();
    }
}
exports.GsubAlternateReader = GsubAlternateReader;
class GsubMultiWriter extends GsubMultiAlternateWriterBase {
    canBeUsed(l) {
        return l.type === ot_layout_1.Gsub.LookupType.Multi;
    }
    getLookupTypeSymbol() {
        return ot_layout_1.Gsub.LookupType.Multi;
    }
    getLookupType() {
        return 2;
    }
}
exports.GsubMultiWriter = GsubMultiWriter;
class GsubAlternateWriter extends GsubMultiAlternateWriterBase {
    canBeUsed(l) {
        return l.type === ot_layout_1.Gsub.LookupType.Alternate;
    }
    getLookupTypeSymbol() {
        return ot_layout_1.Gsub.LookupType.Alternate;
    }
    getLookupType() {
        return 3;
    }
}
exports.GsubAlternateWriter = GsubAlternateWriter;
//# sourceMappingURL=gsub-multi-alternate.js.map