/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { Range3d } from "@itwin/core-geometry";
import { Feature } from "@itwin/core-common";
import { lineCodeFromLinePixels } from "./LineCode";
import { assert } from "@itwin/core-bentley";
const invalidFeature = new Feature();
/** Used internally by [[RenderInstancesParamsBuilder]] to produce an InstancedGraphicProps.
 * Use [[add]] to append [[Instance]]s, then [[finish]] to obtain an InstancedGraphicProps.
 */
export class InstancedGraphicPropsBuilder {
    _instances = [];
    _transformRange = new Range3d();
    _haveSymbology = false;
    add(instance) {
        this._instances.push(instance);
        this._transformRange.extendXYZ(instance.transform.origin.x, instance.transform.origin.y, instance.transform.origin.z);
        if (instance.symbology) {
            this._haveSymbology = true;
        }
    }
    get length() { return this._instances.length; }
    finish(featureTable) {
        const count = this.length;
        if (0 === count) {
            throw new Error("No instances defined");
        }
        const tfc = this._transformRange.center;
        const transformCenter = { x: tfc.x, y: tfc.y, z: tfc.z };
        const transforms = new Float32Array(count * 12);
        const featureIds = featureTable ? new Uint8Array(count * 3) : undefined;
        const symbologyOverrides = this._haveSymbology ? new Uint8Array(count * 8) : undefined;
        for (let i = 0; i < count; i++) {
            const instance = this._instances[i];
            if (featureIds) {
                const feature = typeof instance.feature === "string" ? new Feature(instance.feature) : instance.feature;
                assert(undefined !== featureTable); // otherwise featureIds would be undefined
                const featureIndex = featureTable.insert(feature ?? invalidFeature);
                featureIds[i * 3 + 0] = featureIndex & 0xff;
                featureIds[i * 3 + 1] = (featureIndex & 0xff00) >> 8;
                featureIds[i * 3 + 2] = (featureIndex & 0xff0000) >> 16;
            }
            const symb = instance.symbology;
            if (symbologyOverrides && symb) {
                const ovrIdx = i * 8;
                let flags = 0 /* OvrFlags.None */;
                const weight = symb.weight;
                if (undefined !== weight) {
                    symbologyOverrides[ovrIdx + 1] = Math.max(1, Math.min(31, weight));
                    flags |= 128 /* OvrFlags.Weight */;
                }
                if (undefined !== symb.linePixels) {
                    symbologyOverrides[ovrIdx + 2] = lineCodeFromLinePixels(symb.linePixels);
                    flags |= 64 /* OvrFlags.LineCode */;
                }
                if (undefined !== symb.color) {
                    symbologyOverrides[ovrIdx + 4] = Math.max(0, Math.min(symb.color.r, 255));
                    symbologyOverrides[ovrIdx + 5] = Math.max(0, Math.min(symb.color.g, 255));
                    symbologyOverrides[ovrIdx + 6] = Math.max(0, Math.min(symb.color.b, 255));
                    flags |= 2 /* OvrFlags.Rgb */;
                }
                symbologyOverrides[ovrIdx] = flags;
            }
            const tf = instance.transform;
            const org = [tf.origin.x - tfc.x, tf.origin.y - tfc.y, tf.origin.z - tfc.z];
            const tfIdx = i * 12;
            transforms[tfIdx + 0] = tf.matrix.coffs[0];
            transforms[tfIdx + 1] = tf.matrix.coffs[1];
            transforms[tfIdx + 2] = tf.matrix.coffs[2];
            transforms[tfIdx + 3] = org[0];
            transforms[tfIdx + 4] = tf.matrix.coffs[3];
            transforms[tfIdx + 5] = tf.matrix.coffs[4];
            transforms[tfIdx + 6] = tf.matrix.coffs[5];
            transforms[tfIdx + 7] = org[1];
            transforms[tfIdx + 8] = tf.matrix.coffs[6];
            transforms[tfIdx + 9] = tf.matrix.coffs[7];
            transforms[tfIdx + 10] = tf.matrix.coffs[8];
            transforms[tfIdx + 11] = org[2];
        }
        return {
            count,
            transforms,
            transformCenter,
            featureIds,
            symbologyOverrides,
        };
    }
}
//# sourceMappingURL=InstancedGraphicPropsBuilder.js.map