"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TupleVariationRead = 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 flags_1 = require("../shared/flags");
const iup_1 = require("../shared/iup");
const runs_1 = require("../shared/runs");
exports.TupleVariationRead = (0, bin_util_1.Read)((view, client, vsr) => {
    const dimensions = client.dimensions;
    let totalPoints = 0;
    for (const c of client.contours) {
        totalPoints += ImpLib.Arith.rowCount(c, client.dimensions);
    }
    const _tupleVariationCount = view.uint16();
    const vwData = view.ptr16();
    const tvhList = [];
    for (let ixTvh = 0; ixTvh < (_tupleVariationCount & flags_1.TvhSetFlags.COUNT_MASK); ixTvh++) {
        tvhList.push(view.next(TupleVariationHeader, vsr));
    }
    let sharedPoints = null;
    if (_tupleVariationCount & flags_1.TvhSetFlags.SHARED_POINT_NUMBERS) {
        sharedPoints = vwData.next(PointNumbers, totalPoints);
    }
    const vwPrivateData = vwData.liftRelative(0);
    let startByte = 0;
    for (const tvh of tvhList) {
        const vwTvd = vwPrivateData.lift(startByte);
        let points = null;
        if (tvh.hasPrivatePoints) {
            points = vwTvd.next(PointNumbers, totalPoints);
        }
        else {
            points = sharedPoints;
        }
        if (!points)
            throw errors_1.Errors.Variation.MissingPoints();
        for (let d = 0; d < dimensions; d++) {
            const deltas = vwTvd.next(Deltas, points);
            (0, iup_1.inferDeltas)(dimensions, d, client.contours, tvh.master, deltas);
        }
        startByte += tvh.variationDataSize;
    }
    return client.finish();
});
const TupleVariationHeader = (0, bin_util_1.Read)((view, vsr) => {
    const variationDataSize = view.uint16();
    const _tupleIndex = view.uint16();
    const peakTuple = _tupleIndex & flags_1.TvhFlags.EMBEDDED_PEAK_TUPLE
        ? view.array(vsr.designSpace.length, primitive_1.F2D14)
        : vsr.sharedTuples[_tupleIndex & flags_1.TvhFlags.TUPLE_INDEX_MASK];
    if (!peakTuple) {
        throw errors_1.Errors.Variation.MissingPeakTuple();
    }
    const startTuple = _tupleIndex & flags_1.TvhFlags.INTERMEDIATE_REGION
        ? view.array(vsr.designSpace.length, primitive_1.F2D14)
        : null;
    const endTuple = _tupleIndex & flags_1.TvhFlags.INTERMEDIATE_REGION
        ? view.array(vsr.designSpace.length, primitive_1.F2D14)
        : null;
    const dims = [];
    for (let aid = 0; aid < vsr.designSpace.length; aid++) {
        const dim = vsr.designSpace.at(aid);
        const peak = peakTuple[aid];
        const mDim = startTuple && endTuple
            ? { dim: dim, min: startTuple[aid], peak: peak, max: endTuple[aid] }
            : createMasterDimFromPeak(dim, peak);
        dims.push(mDim);
    }
    return {
        master: new variance_1.OtVar.Master(dims),
        variationDataSize,
        hasPrivatePoints: !!(_tupleIndex & flags_1.TvhFlags.PRIVATE_POINT_NUMBERS)
    };
});
function createMasterDimFromPeak(dim, peak) {
    if (peak > 0)
        return { dim: dim, min: 0, peak, max: peak };
    else if (peak < 0)
        return { dim: dim, min: peak, peak, max: 0 };
    else
        return { dim: dim, min: 0, peak: 0, max: 0 };
}
function Iota(a, b) {
    const as = [];
    for (let x = a; x < b; x++)
        as.push(x);
    return as;
}
const PointNumbers = (0, bin_util_1.Read)((view, nPoints) => {
    const pointCount = view.next(runs_1.PointCount);
    if (pointCount == null)
        return Iota(0, nPoints);
    let currentPoint = 0;
    const points = [];
    while (points.length < pointCount) {
        currentPoint = view.next(runs_1.PointNumberRun, currentPoint, points);
    }
    return points;
});
const Deltas = (0, bin_util_1.Read)((view, points) => {
    let deltasParsed = 0;
    const deltas = [];
    while (deltasParsed < points.length) {
        deltasParsed = view.next(runs_1.DeltaRun, deltasParsed, points, deltas);
    }
    return deltas;
});
//# sourceMappingURL=index.js.map