import { isEqual, uniqWith } from "lodash";
import { CompositeLayer } from "@deck.gl/core";
import { PrivatePolylinesLayer } from "../polylines/privatePolylinesLayer";
import { GpglValueMappedSurfaceLayer, } from "../gpglLayers/gpglValueMappedSurfaceLayer";
import { createPropertyData, computeBoundingBox } from "../utils/layerTools";
import { addPoints3D } from "../../utils";
const defaultCageProps = {
    widthUnits: "meters",
    lineWidth: 2,
    color: [255, 100, 0],
    visible: true,
};
const defaultProps = {
    "@@type": "SeismicLayer",
    name: "SeismicLayer",
    id: "seismic-layer",
    cage: defaultCageProps,
    seismicFences: [],
    material: {
        ambient: 0.35,
        diffuse: 0.9,
        shininess: 32,
        specularColor: [38, 38, 38],
    },
    smoothShading: false,
    pickable: true,
    visible: true,
    depthTest: true,
    ZIncreasingDownwards: true,
};
export default class SeismicLayer extends CompositeLayer {
    initializeState() {
        const cageAttributes = this.rebuildCageAttributes(true);
        this.setState({
            cageAttributes,
        });
    }
    updateState({ props, oldProps }) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        const needs_reload_cage = !isEqual((_a = props.cage) === null || _a === void 0 ? void 0 : _a.origin, (_b = oldProps.cage) === null || _b === void 0 ? void 0 : _b.origin) ||
            !isEqual((_c = props.cage) === null || _c === void 0 ? void 0 : _c.edgeU, (_d = oldProps.cage) === null || _d === void 0 ? void 0 : _d.edgeU) ||
            !isEqual((_e = props.cage) === null || _e === void 0 ? void 0 : _e.edgeV, (_f = oldProps.cage) === null || _f === void 0 ? void 0 : _f.edgeV) ||
            !isEqual((_g = props.cage) === null || _g === void 0 ? void 0 : _g.edgeW, (_h = oldProps.cage) === null || _h === void 0 ? void 0 : _h.edgeW) ||
            !isEqual(props.ZIncreasingDownwards, oldProps.ZIncreasingDownwards);
        if (needs_reload_cage) {
            const cageAttributes = this.rebuildCageAttributes(false);
            this.setState(Object.assign(Object.assign({}, this.state), { cageAttributes }));
        }
        const needs_reload_fences = !isEqual(props.seismicFences.length, (_j = oldProps.seismicFences) === null || _j === void 0 ? void 0 : _j.length) ||
            props.seismicFences.some((fence, index) => {
                var _a;
                const oldFence = (_a = oldProps.seismicFences) === null || _a === void 0 ? void 0 : _a[index];
                return (
                // do not use isEqual for performance: it iterates on each element
                fence.topology !== (oldFence === null || oldFence === void 0 ? void 0 : oldFence.topology) ||
                    fence.vertices !== (oldFence === null || oldFence === void 0 ? void 0 : oldFence.vertices) ||
                    fence.normals !== (oldFence === null || oldFence === void 0 ? void 0 : oldFence.normals) ||
                    fence.texCoords !== (oldFence === null || oldFence === void 0 ? void 0 : oldFence.texCoords) ||
                    //fence.seismicData !== oldFence?.seismicData ||
                    fence.vertexIndices.value !==
                        (oldFence === null || oldFence === void 0 ? void 0 : oldFence.vertexIndices.value) ||
                    fence.vertexIndices.size !== (oldFence === null || oldFence === void 0 ? void 0 : oldFence.vertexIndices.size));
            });
        if (needs_reload_fences) {
            const fences = this.rebuildFencesAttributes();
            this.setState(Object.assign(Object.assign({}, this.state), { seismicFences: fences !== null && fences !== void 0 ? fences : [] }));
        }
    }
    rebuildCageAttributes(reportBoundingBox) {
        const cageDataArrays = this.loadCageData();
        if (typeof this.props.reportBoundingBox === "function" &&
            reportBoundingBox) {
            const boundingBox = computeBoundingBox(cageDataArrays.positions);
            this.props.reportBoundingBox({ layerBoundingBox: boundingBox });
        }
        return {
            length: cageDataArrays.linesCount,
            startIndices: cageDataArrays.startIndices,
            attributes: {
                getPath: {
                    value: cageDataArrays.positions,
                    size: 3,
                },
            },
        };
    }
    loadCageData() {
        // build the list of vertices to represent the cage
        const cage = this.props.cage;
        const pO = cage.origin;
        const pU = addPoints3D(cage.origin, cage.edgeU);
        const pV = addPoints3D(cage.origin, cage.edgeV);
        const pW = addPoints3D(cage.origin, cage.edgeW);
        const pUV = addPoints3D(pU, cage.edgeV);
        const pUW = addPoints3D(pU, cage.edgeW);
        const pVW = addPoints3D(pV, cage.edgeW);
        const pUVW = addPoints3D(pUV, cage.edgeW);
        const vertices = [
            ...pO, // base side
            ...pU,
            ...pUV,
            ...pV,
            ...pO,
            ...pW, // front side
            ...pUW,
            ...pU,
            ...pUV, // right side
            ...pUVW,
            ...pUW,
            ...pW, // top side
            ...pVW,
            ...pUVW,
            ...pVW, // junction
            ...pV, // close back and left sides
        ];
        return {
            positions: new Float32Array(vertices),
            linesCount: 1,
            startIndices: new Uint32Array([0, vertices.length / 3]),
        };
    }
    rebuildFencesAttributes() {
        return this.props.seismicFences;
    }
    getPickingInfo({ info }) {
        var _a, _b;
        if (!info.color) {
            return info;
        }
        const layer_properties = [];
        const zScale = this.props.modelMatrix ? this.props.modelMatrix[10] : 1;
        if (((_a = info.coordinate) === null || _a === void 0 ? void 0 : _a[2]) !== undefined) {
            const depth = (this.props.ZIncreasingDownwards
                ? -info.coordinate[2]
                : info.coordinate[2]) / Math.max(0.001, zScale);
            layer_properties.push(createPropertyData("Depth", depth));
        }
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        const merged_props = [...layer_properties, ...((_b = info.properties) !== null && _b !== void 0 ? _b : [])];
        const properties = uniqWith(merged_props, (e1, e2) => e1.name === e2.name);
        return Object.assign(Object.assign({}, info), { properties });
    }
    renderLayers() {
        var _a, _b;
        const cage = this.state["cageAttributes"];
        const cageLayer = new PrivatePolylinesLayer(this.getSubLayerProps({
            id: "polylines-layer",
            widthUnits: this.props.cage.widthUnits,
            billboard: true,
            jointRounded: true,
            capRounded: true,
            data: cage,
            _pathType: "open",
            getColor: () => this.props.cage.color,
            getWidth: () => this.props.cage.lineWidth,
            updateTriggers: {
                getColor: [this.props.cage.color],
                getWidth: [this.props.cage.lineWidth],
            },
            visible: (_a = this.props.cage.visible) !== null && _a !== void 0 ? _a : defaultCageProps.visible,
            pickable: this.props.pickable,
            depthTest: this.props.depthTest,
            ZIncreasingDownwards: this.props.ZIncreasingDownwards,
        }));
        const seismicFences = this.state["seismicFences"];
        const seismicLayer = new GpglValueMappedSurfaceLayer(this.getSubLayerProps({
            id: `seismic-fence-layer`,
            valueMappedTriangles: seismicFences,
            showMesh: this.props.showMesh,
            colormap: this.props.colormap,
            colormapSetup: this.props.colormapSetup,
            material: this.props.material === true
                ? defaultProps.material
                : this.props.material,
            smoothShading: (_b = this.props.smoothShading) !== null && _b !== void 0 ? _b : defaultProps.smoothShading,
            pickable: this.props.pickable,
            depthTest: this.props.depthTest,
            ZIncreasingDownwards: this.props.ZIncreasingDownwards,
        }));
        return [cageLayer, seismicLayer];
    }
}
SeismicLayer.layerName = "SeismicLayer";
SeismicLayer.defaultProps = defaultProps;
//# sourceMappingURL=seismicLayer.js.map