var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { isEqual } from "lodash";
import { CompositeLayer } from "@deck.gl/core";
import workerpool from "workerpool";
import PrivateTriangleLayer from "./privateTriangleLayer";
import { makeFullMesh } from "./webworker";
import config from "../../SubsurfaceConfig.json";
import { findConfig } from "../../utils/configTools";
// init workerpool
const workerPoolConfig = findConfig(config, "config/workerpool", "config/layer/TriangleLayer/workerpool");
const pool = workerpool.pool(Object.assign({
    maxWorkers: 10,
    workerType: "web",
}, workerPoolConfig));
function onTerminateWorker() {
    const stats = pool.stats();
    if (stats.busyWorkers === 0 && stats.pendingTasks === 0) {
        pool.terminate();
    }
}
function loadData(pointsData, triangleData) {
    return __awaiter(this, void 0, void 0, function* () {
        // Keep
        //const t0 = performance.now();
        //-- Vertexes --
        let vertexArray = new Float32Array();
        if (Array.isArray(pointsData)) {
            // Input data is native javascript array.
            vertexArray = new Float32Array(pointsData);
        }
        else if (pointsData instanceof Float32Array) {
            vertexArray = pointsData;
        }
        else {
            // Input data is an URL.
            const response_mesh = yield fetch(pointsData);
            if (!response_mesh.ok) {
                console.error("Could not load vertex data");
            }
            const blob_mesh = yield response_mesh.blob();
            // Load as binary array of floats.
            const buffer = yield blob_mesh.arrayBuffer();
            vertexArray = new Float32Array(buffer);
        }
        //-- Triangle indexes --
        let indexArray;
        if (Array.isArray(triangleData)) {
            // Input data is native javascript array.
            indexArray = new Uint32Array(triangleData);
        }
        else if (triangleData instanceof Uint32Array) {
            indexArray = triangleData;
        }
        else {
            // Input data is an URL.
            const response_mesh = yield fetch(triangleData);
            if (!response_mesh.ok) {
                console.error("Could not load triangle index data");
            }
            const blob_mesh = yield response_mesh.blob();
            // Load as binary array of floats.
            const buffer = yield blob_mesh.arrayBuffer();
            indexArray = new Uint32Array(buffer);
        }
        //const t1 = performance.now();
        // Keep this.
        //console.log(`Task loading took ${(t1 - t0) * 0.001}  seconds.`);
        return Promise.all([vertexArray, indexArray]);
    });
}
const defaultProps = {
    "@@type": "TriangleLayer",
    name: "TriangleLayer",
    id: "triangle-layer",
    pickable: true,
    visible: true,
    contours: [-1.0, -1.0],
    color: [100, 100, 255],
    gridLines: false,
    smoothShading: true,
    material: true,
    depthTest: true,
    ZIncreasingDownwards: true,
    debug: false,
};
export default class TriangleLayer extends CompositeLayer {
    get isLoaded() {
        var _a;
        const subLayers = this.getSubLayers();
        const isLoaded = super.isLoaded &&
            subLayers.length > 0 &&
            subLayers.every((layer) => layer.isLoaded);
        const isFinishedLoading = (_a = this.state) === null || _a === void 0 ? void 0 : _a["isFinishedLoading"];
        const isFinished = isFinishedLoading !== null && isFinishedLoading !== void 0 ? isFinishedLoading : false;
        //const isFinished = this.state?.["isFinishedLoading"] ?? false;
        return isLoaded && isFinished;
    }
    rebuildData(reportBoundingBox) {
        const pointsData = this.props.pointsData;
        const triangleData = this.props.triangleData;
        const p = loadData(pointsData, triangleData);
        p.then(([vertexArray, indexArray]) => {
            // Using inline web worker for calculating the triangle mesh from
            // loaded input data so not to halt the GUI thread.
            const webworkerParams = {
                vertexArray,
                indexArray,
                smoothShading: this.props.smoothShading,
                displayNormals: this.props.debug,
            };
            pool.exec(makeFullMesh, [{ data: webworkerParams }]).then((e) => {
                const [geometryTriangles, geometryLines] = e;
                this.setState({
                    geometryTriangles,
                    geometryLines,
                });
                if (typeof this.props.reportBoundingBox !== "undefined" &&
                    reportBoundingBox) {
                    let xmax = -99999999;
                    let xmin = 99999999;
                    let ymax = -99999999;
                    let ymin = 99999999;
                    let zmax = -99999999;
                    let zmin = 99999999;
                    for (let i = 0; i < vertexArray.length / 3; i++) {
                        xmax =
                            vertexArray[3 * i + 0] > xmax
                                ? vertexArray[3 * i + 0]
                                : xmax; //eslint-disable-line
                        xmin =
                            vertexArray[3 * i + 0] < xmin
                                ? vertexArray[3 * i + 0]
                                : xmin; //eslint-disable-line
                        ymax =
                            vertexArray[3 * i + 1] > ymax
                                ? vertexArray[3 * i + 1]
                                : ymax; //eslint-disable-line
                        ymin =
                            vertexArray[3 * i + 1] < ymin
                                ? vertexArray[3 * i + 1]
                                : ymin; //eslint-disable-line
                        zmax =
                            vertexArray[3 * i + 2] > zmax
                                ? vertexArray[3 * i + 2]
                                : zmax; //eslint-disable-line
                        zmin =
                            vertexArray[3 * i + 2] < zmin
                                ? vertexArray[3 * i + 2]
                                : zmin; //eslint-disable-line
                    }
                    if (this.props.ZIncreasingDownwards) {
                        const tmp = zmin;
                        zmin = zmax;
                        zmax = tmp;
                    }
                    this.props.reportBoundingBox({
                        layerBoundingBox: [xmin, ymin, zmin, xmax, ymax, zmax],
                    });
                }
                this.setState(Object.assign(Object.assign({}, this.state), { isFinishedLoading: true }));
                onTerminateWorker();
            });
        });
    }
    initializeState() {
        this.setState(Object.assign(Object.assign({}, this.state), { isFinishedLoading: false }));
        const reportBoundingBox = true;
        this.rebuildData(reportBoundingBox);
    }
    updateState({ props, oldProps }) {
        const needs_reload = !isEqual(props.debug, oldProps.debug) ||
            !isEqual(props.pointsData, oldProps.pointsData) ||
            !isEqual(props.triangleData, oldProps.triangleData) ||
            !isEqual(props.ZIncreasingDownwards, oldProps.ZIncreasingDownwards);
        if (needs_reload) {
            this.setState(Object.assign(Object.assign({}, this.state), { isFinishedLoading: false }));
            const reportBoundingBox = false;
            this.rebuildData(reportBoundingBox);
        }
    }
    renderLayers() {
        if (Object.keys(this.state).length === 1) {
            // isFinishedLoading only in state
            return [];
        }
        const enableLighting = this.props.material !== false;
        const layer = new PrivateTriangleLayer(this.getSubLayerProps({
            geometryTriangles: this.state["geometryTriangles"],
            geometryLines: this.state["geometryLines"],
            pickable: this.props.pickable,
            contours: this.props.contours,
            gridLines: this.props.gridLines,
            color: this.props.color,
            material: this.props.material,
            smoothShading: this.props.smoothShading,
            depthTest: this.props.depthTest,
            ZIncreasingDownwards: this.props.ZIncreasingDownwards,
            enableLighting,
        }));
        return [layer];
    }
}
TriangleLayer.layerName = "TriangleLayer";
TriangleLayer.defaultProps = defaultProps;
//# sourceMappingURL=triangleLayer.js.map