"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseTableIo = void 0;
const bin_composite_types_1 = require("@ot-builder/bin-composite-types");
const errors_1 = require("@ot-builder/errors");
const ot_layout_1 = require("@ot-builder/ot-layout");
const primitive_1 = require("@ot-builder/primitive");
const var_store_1 = require("@ot-builder/var-store");
const variance_1 = require("@ot-builder/variance");
const coord_1 = require("./coord");
exports.BaseTableIo = {
    read(view, gOrd, designSpace) {
        const majorVersion = view.uint16();
        const minorVersion = view.uint16();
        errors_1.Assert.SubVersionSupported("BASETable", majorVersion, minorVersion, [1, 0], [1, 1]);
        const pHorizontalAxis = view.ptr16Nullable();
        const pVerticalAxis = view.ptr16Nullable();
        let ivs = null;
        if (minorVersion === 1) {
            const pIVS = view.ptr32Nullable();
            if (pIVS && designSpace)
                ivs = var_store_1.ReadTimeIVS.read(pIVS, designSpace);
        }
        const base = new ot_layout_1.Base.Table();
        if (pHorizontalAxis)
            base.horizontal = pHorizontalAxis.next(AxisTable, gOrd, ivs);
        if (pVerticalAxis)
            base.vertical = pVerticalAxis.next(AxisTable, gOrd, ivs);
        return base;
    },
    write(frag, table, gOrd, designSpace) {
        const ivs = designSpace
            ? var_store_1.WriteTimeIVS.create(new variance_1.OtVar.MasterSet())
            : null;
        frag.uint16(1);
        const hMinorVersion = frag.reserve(primitive_1.UInt16);
        frag.push(Ptr16AxisTableNullable, table.horizontal, gOrd, ivs);
        frag.push(Ptr16AxisTableNullable, table.vertical, gOrd, ivs);
        if (designSpace && ivs && !ivs.isEmpty()) {
            hMinorVersion.fill(1);
            frag.ptr32New().push(var_store_1.WriteTimeIVS, ivs, { designSpace });
        }
        else {
            hMinorVersion.fill(0);
        }
    }
};
const AxisTable = {
    read(view, gOrd, ivs) {
        const ax = new ot_layout_1.Base.AxisTable();
        ax.baselineTags = view.next(Ptr16BaseTagListNullable);
        ax.scripts = new Map(view.next(Ptr16BaseScriptList, ax.baselineTags, gOrd, ivs));
        return ax;
    },
    write(frag, ax, gOrd, ivs) {
        const sortedTags = ax.baselineTags ? [...ax.baselineTags].sort() : null;
        frag.push(Ptr16BaseTagListNullable, sortedTags);
        const baseScriptList = [...ax.scripts].sort(byTagOrder);
        frag.push(Ptr16BaseScriptList, baseScriptList, sortedTags, gOrd, ivs);
    }
};
const Ptr16AxisTableNullable = (0, bin_composite_types_1.NullablePtr16)(AxisTable);
const BaseTagList = {
    read(view) {
        const baseTagCount = view.uint16();
        const tags = [];
        for (let tid = 0; tid < baseTagCount; tid++)
            tags[tid] = view.next(primitive_1.Tag);
        return tags;
    },
    write(frag, tags) {
        errors_1.Assert.NoGap("BaseTagList", tags);
        frag.uint16(tags.length);
        for (let tid = 0; tid < tags.length; tid++)
            frag.push(primitive_1.Tag, tags[tid]);
    }
};
const Ptr16BaseTagListNullable = (0, bin_composite_types_1.NullablePtr16)(BaseTagList);
const BaseScriptRecord = {
    read(view, baseTags, gOrd, ivs) {
        const tag = view.next(primitive_1.Tag);
        const baseScript = view.next(Ptr16BaseScript, baseTags, gOrd, ivs);
        return [tag, baseScript];
    },
    write(frag, [tag, bs], sortedBaseTags, gOrd, ivs) {
        frag.push(primitive_1.Tag, tag);
        frag.push(Ptr16BaseScript, bs, sortedBaseTags, gOrd, ivs);
    }
};
const Ptr16BaseScriptList = (0, bin_composite_types_1.NonNullablePtr16)((0, bin_composite_types_1.SimpleArray)(primitive_1.UInt16, BaseScriptRecord));
const BaseScript = {
    read(view, baseTags, gOrd, ivs) {
        const script = new ot_layout_1.Base.Script();
        script.baseValues = view.next(Ptr16BaseValuesNullable, baseTags, gOrd, ivs);
        script.defaultMinMax = view.next(Ptr16MinMaxTableNullable, gOrd, ivs);
        const baseLangSysCount = view.uint16();
        for (let lid = 0; lid < baseLangSysCount; lid++) {
            const tag = view.next(primitive_1.Tag);
            const mmt = view.next(Ptr16MinMaxTable, gOrd, ivs);
            if (!script.baseLangSysRecords)
                script.baseLangSysRecords = new Map();
            script.baseLangSysRecords.set(tag, mmt);
        }
        return script;
    },
    write(frag, script, sortedBaseTags, gOrd, ivs) {
        frag.push(Ptr16BaseValuesNullable, script.baseValues, sortedBaseTags, gOrd, ivs);
        frag.push(Ptr16MinMaxTableNullable, script.defaultMinMax, gOrd, ivs);
        if (script.baseLangSysRecords && script.baseLangSysRecords.size) {
            const baseLangSysList = [...script.baseLangSysRecords].sort(byTagOrder);
            frag.uint16(baseLangSysList.length);
            for (const [tag, mmt] of baseLangSysList) {
                frag.push(primitive_1.Tag, tag);
                frag.push(Ptr16MinMaxTable, mmt, gOrd, ivs);
            }
        }
        else {
            frag.uint16(0);
        }
    }
};
const Ptr16BaseScript = (0, bin_composite_types_1.NonNullablePtr16)(BaseScript);
const BaseValues = {
    read(view, baseTags, gOrd, ivs) {
        if (!baseTags)
            throw errors_1.Errors.NullPtr(`AxisTable::baseTagListOffset`);
        const bv = new ot_layout_1.Base.BaseValues();
        bv.defaultBaselineIndex = view.uint16();
        const baseCoordCount = view.uint16();
        errors_1.Assert.SizeMatch(`BaseValues::baseCoordCount`, baseCoordCount, baseTags.length);
        for (let cid = 0; cid < baseCoordCount; cid++) {
            bv.baseValues.set(baseTags[cid], view.ptr16().next(coord_1.BaseCoord, gOrd, ivs));
        }
        return bv;
    },
    write(frag, bv, sortedBaseTags, gOrd, ivs) {
        if (!sortedBaseTags)
            throw errors_1.Errors.NullPtr(`AxisTable::baseTagListOffset`);
        frag.uint16(bv.defaultBaselineIndex);
        frag.uint16(sortedBaseTags.length);
        for (const tag of sortedBaseTags) {
            const coord = bv.baseValues.get(tag);
            if (!coord)
                throw errors_1.Errors.NullPtr(`BaseValues::baseCoords @ ${tag}`);
            frag.push(coord_1.Ptr16BaseCoord, coord, gOrd, ivs);
        }
    }
};
const Ptr16BaseValuesNullable = (0, bin_composite_types_1.NullablePtr16)(BaseValues);
const MinMaxTable = {
    read(view, gOrd, ivs) {
        const defaultMinMax = view.next(MinMaxValue, gOrd, ivs);
        const featMinMaxCount = view.uint16();
        const featMinMax = new Map();
        for (let fid = 0; fid < featMinMaxCount; fid++) {
            const featureTableTag = view.next(primitive_1.Tag);
            const mm = view.next(MinMaxValue, gOrd, ivs);
            featMinMax.set(featureTableTag, mm);
        }
        return new ot_layout_1.Base.MinMaxTable(defaultMinMax, featMinMax);
    },
    write(frag, mmt, gOrd, ivs) {
        frag.push(MinMaxValue, mmt.defaultMinMax, gOrd, ivs);
        if (mmt.featMinMax && mmt.featMinMax.size) {
            const fmmList = [...mmt.featMinMax].sort(byTagOrder);
            frag.uint16(fmmList.length);
            for (const [tag, mm] of fmmList) {
                frag.push(primitive_1.Tag, tag);
                frag.push(MinMaxValue, mm, gOrd, ivs);
            }
        }
        else {
            frag.uint16(0);
        }
    }
};
const Ptr16MinMaxTable = (0, bin_composite_types_1.NonNullablePtr16)(MinMaxTable);
const Ptr16MinMaxTableNullable = (0, bin_composite_types_1.NullablePtr16)(MinMaxTable);
const MinMaxValue = {
    read(view, gOrd, ivs) {
        return {
            minCoord: view.next(coord_1.Ptr16BaseCoordNullable, gOrd, ivs),
            maxCoord: view.next(coord_1.Ptr16BaseCoordNullable, gOrd, ivs)
        };
    },
    write(frag, mm, gOrd, ivs) {
        frag.push(coord_1.Ptr16BaseCoordNullable, mm.minCoord, gOrd, ivs);
        frag.push(coord_1.Ptr16BaseCoordNullable, mm.maxCoord, gOrd, ivs);
    }
};
function byTagOrder(a, b) {
    return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
}
//# sourceMappingURL=index.js.map