"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WriteTimeIVS = exports.ReadTimeIVS = void 0;
const tslib_1 = require("tslib");
const bin_util_1 = require("@ot-builder/bin-util");
const ImpLib = tslib_1.__importStar(require("@ot-builder/common-impl"));
const errors_1 = require("@ot-builder/errors");
const primitive_1 = require("@ot-builder/primitive");
const variance_1 = require("@ot-builder/variance");
const general_1 = require("./general");
const RegionList = {
    ...(0, bin_util_1.Read)((vw, designSpace, ivs) => {
        const axisCount = vw.uint16();
        errors_1.Assert.Variation.AxesCountMatch("IVS::VariationRegionList::axisCount", axisCount, "fvar::axisCount", designSpace.length);
        const regionCount = vw.uint16();
        for (const [pRegion] of vw.repeat(regionCount)) {
            const spans = [];
            for (const [pAxis, axisIndex] of pRegion.repeat(axisCount)) {
                const min = pAxis.next(primitive_1.F2D14);
                const peak = pAxis.next(primitive_1.F2D14);
                const max = pAxis.next(primitive_1.F2D14);
                spans.push({ dim: designSpace.at(axisIndex), min, peak, max });
            }
            ivs.knownMasters.push(new variance_1.OtVar.Master(spans));
        }
    }),
    ...(0, bin_util_1.Write)((fr, regions, ds) => {
        errors_1.Assert.NotOverflow("VariationRegionList::regionCount", regions.length, 0x7fff);
        fr.uint16(ds.length); // axesCount
        fr.uint16(regions.length); // regionCount
        for (const region of ImpLib.Iterators.ArrToCount(regions, new variance_1.OtVar.Master([]))) {
            const m = new Map();
            for (const dim of region.regions) {
                m.set(dim.dim, dim);
            }
            for (const dim of ds) {
                const mDim = m.get(dim);
                fr.array(primitive_1.F2D14, mDim ? [mDim.min, mDim.peak, mDim.max] : [-1, 0, 1]);
            }
        }
    })
};
function createIVD() {
    return new general_1.ReadTimeIVD(new variance_1.OtVar.ValueFactory(new variance_1.OtVar.MasterSet()));
}
function createIVS() {
    return new general_1.CReadTimeIVS(variance_1.OtVar.Ops);
}
const IVD = {
    ...(0, bin_util_1.Read)(vw => {
        const ivd = createIVD();
        const itemCount = vw.uint16();
        const fLong_wordDeltaCount = vw.uint16();
        const regionIndexCount = vw.uint16();
        for (const [p, index] of vw.repeat(regionIndexCount)) {
            ivd.masterIDs[index] = p.uint16();
        }
        const fLongWords = fLong_wordDeltaCount & 0x8000, wordDeltaCount = fLong_wordDeltaCount & 0x7fff;
        for (const [p, jItem] of vw.repeat(itemCount)) {
            const deltas = [];
            for (let jDelta = 0; jDelta < regionIndexCount; jDelta++) {
                if (jDelta < wordDeltaCount)
                    deltas[jDelta] = fLongWords ? p.int32() : p.int16();
                else
                    deltas[jDelta] = fLongWords ? p.int16() : p.int8();
            }
            ivd.deltas[jItem] = deltas;
        }
        return ivd;
    }),
    ...(0, bin_util_1.Write)((fr, ivd, allowLongDeltas) => {
        const regionCount = ivd.masterIDs.length;
        let wordDeltaCount = 0;
        let useLongDeltas = false;
        // figure out whether we should use long deltas
        if (allowLongDeltas) {
            for (const [deltaRow, innerID] of ivd.entries()) {
                for (let rid = wordDeltaCount; rid < regionCount; rid++) {
                    const delta = Math.round(deltaRow[rid] || 0);
                    if (primitive_1.Int16.from(delta) !== delta)
                        useLongDeltas = true;
                }
            }
        }
        const deltas = [];
        const Longer = useLongDeltas ? primitive_1.Int32 : primitive_1.Int16;
        const Shorter = useLongDeltas ? primitive_1.Int16 : primitive_1.Int8;
        for (const [deltaRow, innerID] of ivd.entries()) {
            for (let rid = wordDeltaCount; rid < regionCount; rid++) {
                const delta = Math.round(deltaRow[rid] || 0);
                if (Shorter.from(delta) !== delta)
                    wordDeltaCount = rid + 1;
            }
            deltas[innerID] = [...deltaRow];
        }
        fr.uint16(deltas.length);
        fr.uint16((useLongDeltas ? 0x8000 : 0) | (wordDeltaCount & 0x7fff));
        fr.uint16(regionCount);
        fr.arrayNF(primitive_1.UInt16, regionCount, ivd.masterIDs, 0);
        for (const [delta, , dim] of ImpLib.Iterators.FlatMatrixSized(deltas, regionCount, 0)) {
            if (dim < wordDeltaCount)
                fr.push(Longer, delta);
            else
                fr.push(Shorter, delta);
        }
    })
};
exports.ReadTimeIVS = {
    Create: createIVS,
    ...(0, bin_util_1.Read)((vw, designSpace) => {
        const format = vw.uint16();
        if (format !== 1)
            throw errors_1.Errors.FormatNotSupported("IVS", format);
        const ivs = createIVS();
        const pRegionList = vw.ptr32();
        pRegionList.next(RegionList, designSpace, ivs);
        const ivdCount = vw.uint16();
        for (const [pIVDOffset] of vw.repeat(ivdCount)) {
            const pIVD = pIVDOffset.ptr32Nullable();
            if (pIVD) {
                ivs.itemVariationData.push(pIVD.next(IVD));
            }
            else {
                ivs.itemVariationData.push(createIVD());
            }
        }
        return ivs;
    })
};
exports.WriteTimeIVS = {
    create(ms) {
        return new general_1.GeneralWriteTimeIVStore(variance_1.OtVar.Ops, ms, 0xfff0);
    },
    ...(0, bin_util_1.Write)((frag, ivs, options) => {
        const masterList = [];
        for (const [m, id] of ivs.masters())
            masterList[id] = m;
        const fr = new bin_util_1.Frag();
        fr.uint16(1);
        fr.ptr32New().push(RegionList, masterList, options.designSpace);
        const ivdList = [...ivs.ivdList()];
        fr.uint16(ivdList.length);
        for (const ivd of ivdList) {
            fr.ptr32New().push(IVD, ivd, !!options.allowLongDeltas);
        }
        frag.bytes(bin_util_1.Frag.pack(fr));
    })
};
//# sourceMappingURL=impl.js.map