import { mat4 } from "gl-matrix";
import { BridgedCameraSource } from "./bridged-camera-source";
import { Pipeline } from "./pipeline";
export class BridgedD3Tracker {
    constructor() {
        this._latestId = 1;
        this._d3StateById = new Map();
        this._identityPose = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
        this._emptyArray = new Float32Array([]);
        this.impl = {
            d3_tracker_create: (pipeline) => {
                const p = Pipeline.get(pipeline);
                if (!p)
                    throw new Error("Invalid pipeline in d3_tracker_create");
                let newId = (this._latestId++);
                let s = {
                    pipeline: p,
                    enabled: true,
                    sizeById: Object.create(null),
                    maxResolution: false,
                };
                this._d3StateById.set(newId, s);
                this._notifyOptionsUpdated(s.pipeline);
                return newId;
            },
            d3_tracker_destroy: (o) => {
                let s = this._getD3State(o);
                this._d3StateById.delete(o);
            },
            d3_tracker_enabled: (o) => {
                let s = this._getD3State(o);
                return s.enabled;
            },
            d3_tracker_enabled_set: (o, enabled) => {
                let s = this._getD3State(o);
                s.enabled = enabled;
                this._notifyOptionsUpdated(s.pipeline);
            },
            d3_tracker_process_max_resolution_set: (o, v) => {
                let s = this._getD3State(o);
                s.maxResolution = v;
                this._notifyOptionsUpdated(s.pipeline);
            },
            d3_tracker_count: (o) => {
                var _a, _b;
                const data = this._getD3Data(o);
                if (!Array.isArray(data === null || data === void 0 ? void 0 : data.detections))
                    return 0;
                return (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
            },
            d3_tracker_id: (o, indx) => {
                var _a, _b, _c;
                const data = this._getD3Data(o);
                return (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : '';
            },
            d3_tracker_qr: (o, indx) => {
                var _a, _b, _c;
                const data = this._getD3Data(o);
                return (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.qr) !== null && _c !== void 0 ? _c : '';
            },
            d3_tracker_pose_raw: (o, indx) => {
                return this.impl.d3_tracker_pose0_raw(o, indx);
            },
            d3_tracker_pose0_raw: (o, indx) => {
                var _a, _b, _c, _d, _e, _f;
                const data = this._getD3Data(o);
                let ret = (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.worldPoses) === null || _c === void 0 ? void 0 : _c[0];
                if (!ret)
                    return this._identityPose;
                if (Array.isArray(ret))
                    ret = new Float32Array(ret);
                let worldToCamera = data === null || data === void 0 ? void 0 : data.worldToCamera;
                if (!worldToCamera)
                    this._identityPose;
                if (Array.isArray(worldToCamera)) {
                    worldToCamera = new Float32Array(worldToCamera);
                    if (data)
                        data.worldToCamera = worldToCamera;
                }
                const computed = mat4.create();
                mat4.multiply(computed, worldToCamera, ret);
                const state = this._getD3State(o);
                const id = (_e = (_d = data === null || data === void 0 ? void 0 : data.detections) === null || _d === void 0 ? void 0 : _d[indx]) === null || _e === void 0 ? void 0 : _e.id;
                if (id && id.length > 0) {
                    const size = 0.5 * ((_f = state.sizeById[id]) !== null && _f !== void 0 ? _f : 2);
                    computed[12] *= size;
                    computed[13] *= size;
                    computed[14] *= size;
                }
                return computed;
            },
            d3_tracker_pose1_raw: (o, indx) => {
                var _a, _b, _c, _d, _e, _f;
                const data = this._getD3Data(o);
                let ret = (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.worldPoses) === null || _c === void 0 ? void 0 : _c[1];
                if (!ret)
                    return this._identityPose;
                if (Array.isArray(ret))
                    ret = new Float32Array(ret);
                let worldToCamera = data === null || data === void 0 ? void 0 : data.worldToCamera;
                if (!worldToCamera)
                    this._identityPose;
                if (Array.isArray(worldToCamera)) {
                    worldToCamera = new Float32Array(worldToCamera);
                    if (data)
                        data.worldToCamera = worldToCamera;
                }
                const computed = mat4.create();
                mat4.multiply(computed, worldToCamera, ret);
                const state = this._getD3State(o);
                const id = (_e = (_d = data === null || data === void 0 ? void 0 : data.detections) === null || _d === void 0 ? void 0 : _d[indx]) === null || _e === void 0 ? void 0 : _e.id;
                if (id && id.length > 0) {
                    const size = 0.5 * ((_f = state.sizeById[id]) !== null && _f !== void 0 ? _f : 2);
                    computed[12] *= size;
                    computed[13] *= size;
                    computed[14] *= size;
                }
                return computed;
            },
            d3_tracker_landmarks_data: (o, indx) => {
                var _a, _b;
                const data = this._getD3Data(o);
                let landmarks = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.landmarks;
                if (!landmarks)
                    return this._emptyArray;
                if (Array.isArray(landmarks)) {
                    landmarks = new Float32Array(landmarks);
                    data.detections[indx].landmarks = landmarks;
                }
                return landmarks;
            },
            d3_tracker_landmarks_data_size: (o, indx) => {
                var _a, _b, _c, _d;
                const data = this._getD3Data(o);
                return (_d = (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.landmarks) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
            },
            d3_tracker_type: (o, indx) => {
                var _a, _b, _c;
                const data = this._getD3Data(o);
                return (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : 0;
            },
            d3_tracker_dense: (o, indx) => {
                var _a, _b, _c;
                const data = this._getD3Data(o);
                return (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.dense) !== null && _c !== void 0 ? _c : 0;
            },
            d3_tracker_category: (o, indx) => {
                var _a, _b, _c;
                const data = this._getD3Data(o);
                return (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.detections) === null || _a === void 0 ? void 0 : _a[indx]) === null || _b === void 0 ? void 0 : _b.category) !== null && _c !== void 0 ? _c : 0;
            },
            d3_tracker_size_for_id_set: (o, id, size) => {
                const state = this._getD3State(o);
                state.sizeById[id] = size;
            },
        };
    }
    static IsSupported() {
        return BridgedCameraSource.IsSupported();
    }
    static SharedInstance() {
        if (!this._sharedInstance) {
            this._sharedInstance = new BridgedD3Tracker();
        }
        return this._sharedInstance;
    }
    _getD3State(o) {
        let s = this._d3StateById.get(o);
        if (!s)
            throw new Error("This object has been destroyed");
        return s;
    }
    _getD3DataFromPipeline(p) {
        var _a, _b, _c;
        return (_c = (_b = (_a = p === null || p === void 0 ? void 0 : p.getCurrentCameraInfo()) === null || _a === void 0 ? void 0 : _a.cameraSourceData) === null || _b === void 0 ? void 0 : _b.frameInfo) === null || _c === void 0 ? void 0 : _c.d3Data;
    }
    _getD3Data(o) {
        let s = this._getD3State(o);
        return this._getD3DataFromPipeline(s.pipeline);
    }
    _notifyOptionsUpdated(p) {
        if (p.currentCameraSource instanceof BridgedCameraSource) {
            p.currentCameraSource.optionsUpdated(this.getCombinedOptionsForPipeline(p));
        }
    }
    getCombinedOptionsForPipeline(p) {
        const options = {};
        for (const state of this._d3StateById.values()) {
            if (state.pipeline !== p)
                continue;
            if (!state.enabled)
                continue;
            options.d3 = true;
            if (state.maxResolution)
                options.d3MaxResolution = true;
        }
        return options;
    }
}
BridgedD3Tracker._sharedInstance = null;
