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 { CompositeLayer } from "@deck.gl/core/typed";
import privateMapLayer from "./privateMapLayer";
import { layersDefaultProps } from "../layersDefaultProps";
import { getModelMatrix } from "../utils/layerTools";
import { isEqual } from "lodash";
import * as png from "@vivaxy/png";
import { makeFullMesh } from "./webworker";
function load_mesh_and_properties(meshUrl, propertiesUrl) {
    return __awaiter(this, void 0, void 0, function* () {
        // Keep
        //const t0 = performance.now();
        const isMesh = typeof meshUrl !== "undefined" && meshUrl !== "";
        const isProperties = typeof propertiesUrl !== "undefined" && propertiesUrl !== "";
        if (!isMesh && !isProperties) {
            console.error("Error. One or both of texture and mesh must be given!");
        }
        if (isMesh && !isProperties) {
            propertiesUrl = meshUrl;
        }
        //-- PROPERTY TEXTURE. --
        const response = yield fetch(propertiesUrl);
        if (!response.ok) {
            console.error("Could not load ", propertiesUrl);
        }
        let propertiesData;
        const blob = yield response.blob();
        const contentType = response.headers.get("content-type");
        const isPng = contentType === "image/png";
        if (isPng) {
            // Load as Png  with abolute float values.
            propertiesData = yield new Promise((resolve) => {
                const fileReader = new FileReader();
                fileReader.readAsArrayBuffer(blob);
                fileReader.onload = () => {
                    const arrayBuffer = fileReader.result;
                    const imgData = png.decode(arrayBuffer);
                    const data = imgData.data; // array of int's
                    const n = data.length;
                    const buffer = new ArrayBuffer(n);
                    const view = new DataView(buffer);
                    for (let i = 0; i < n; i++) {
                        view.setUint8(i, data[i]);
                    }
                    const floatArray = new Float32Array(buffer);
                    resolve(floatArray);
                };
            });
        }
        else {
            // Load as binary array of floats.
            const buffer = yield blob.arrayBuffer();
            propertiesData = new Float32Array(buffer);
        }
        //-- MESH --
        let meshData = new Float32Array();
        if (isMesh) {
            const response_mesh = yield fetch(meshUrl);
            if (!response_mesh.ok) {
                console.error("Could not load ", meshUrl);
            }
            const blob_mesh = yield response_mesh.blob();
            const contentType_mesh = response_mesh.headers.get("content-type");
            const isPng_mesh = contentType_mesh === "image/png";
            if (isPng_mesh) {
                // Load as Png  with abolute float values.
                meshData = yield new Promise((resolve) => {
                    const fileReader = new FileReader();
                    fileReader.readAsArrayBuffer(blob_mesh);
                    fileReader.onload = () => {
                        const arrayBuffer = fileReader.result;
                        const imgData = png.decode(arrayBuffer);
                        const data = imgData.data; // array of int's
                        const n = data.length;
                        const buffer = new ArrayBuffer(n);
                        const view = new DataView(buffer);
                        for (let i = 0; i < n; i++) {
                            view.setUint8(i, data[i]);
                        }
                        const floatArray = new Float32Array(buffer);
                        resolve(floatArray);
                    };
                });
            }
            else {
                // Load as binary array of floats.
                const buffer = yield blob_mesh.arrayBuffer();
                meshData = new Float32Array(buffer);
            }
        }
        //const t1 = performance.now();
        // Keep this.
        //console.log(`Task loading took ${(t1 - t0) * 0.001}  seconds.`);
        return Promise.all([isMesh, meshData, propertiesData]);
    });
}
export default class MapLayer extends CompositeLayer {
    rebuildData(reportBoundingBox) {
        const p = load_mesh_and_properties(this.props.meshUrl, this.props.propertiesUrl);
        p.then(([isMesh, meshData, propertiesData]) => {
            // Using inline web worker for calculating the triangle mesh from
            // loaded input data so not to halt the GUI thread.
            const blob = new Blob(["self.onmessage = ", makeFullMesh.toString()], { type: "text/javascript" });
            const url = URL.createObjectURL(blob);
            const webWorker = new Worker(url);
            const webworkerParams = {
                meshData,
                propertiesData,
                isMesh,
                frame: this.props.frame,
                smoothShading: this.props.smoothShading,
            };
            webWorker.postMessage(webworkerParams);
            webWorker.onmessage = (e) => {
                var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
                const [mesh, mesh_lines, meshZValueRange, propertyValueRange] = e.data;
                const legend = {
                    discrete: false,
                    valueRange: (_a = this.props.colorMapRange) !== null && _a !== void 0 ? _a : propertyValueRange,
                    colorName: this.props.colorMapName,
                    title: "MapLayer",
                    colorMapFunction: this.props.colorMapFunction,
                };
                this.setState({
                    mesh,
                    mesh_lines,
                    propertyValueRange,
                    legend,
                });
                if (typeof this.props.setReportedBoundingBox !== "undefined" &&
                    reportBoundingBox) {
                    const xinc = (_d = (_c = (_b = this.props.frame) === null || _b === void 0 ? void 0 : _b.increment) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : 0;
                    const yinc = (_g = (_f = (_e = this.props.frame) === null || _e === void 0 ? void 0 : _e.increment) === null || _f === void 0 ? void 0 : _f[1]) !== null && _g !== void 0 ? _g : 0;
                    const xcount = (_k = (_j = (_h = this.props.frame) === null || _h === void 0 ? void 0 : _h.count) === null || _j === void 0 ? void 0 : _j[0]) !== null && _k !== void 0 ? _k : 1;
                    const ycount = (_o = (_m = (_l = this.props.frame) === null || _l === void 0 ? void 0 : _l.count) === null || _m === void 0 ? void 0 : _m[1]) !== null && _o !== void 0 ? _o : 1;
                    const xMin = (_r = (_q = (_p = this.props.frame) === null || _p === void 0 ? void 0 : _p.origin) === null || _q === void 0 ? void 0 : _q[0]) !== null && _r !== void 0 ? _r : 0;
                    const yMin = (_u = (_t = (_s = this.props.frame) === null || _s === void 0 ? void 0 : _s.origin) === null || _t === void 0 ? void 0 : _t[1]) !== null && _u !== void 0 ? _u : 0;
                    const zMin = -meshZValueRange[0];
                    const xMax = xMin + xinc * xcount;
                    const yMax = yMin + yinc * ycount;
                    const zMax = -meshZValueRange[0];
                    this.props.setReportedBoundingBox([
                        xMin,
                        yMin,
                        zMin,
                        xMax,
                        yMax,
                        zMax,
                    ]);
                }
                webWorker.terminate();
            };
        });
    }
    initializeState() {
        const reportBoundingBox = true;
        this.rebuildData(reportBoundingBox);
    }
    updateState({ props, oldProps }) {
        const needs_reload = !isEqual(props.meshUrl, oldProps.meshUrl) ||
            !isEqual(props.propertiesUrl, oldProps.propertiesUrl) ||
            !isEqual(props.frame, oldProps.frame) ||
            !isEqual(props.gridLines, oldProps.gridLines);
        if (needs_reload) {
            const reportBoundingBox = false;
            this.rebuildData(reportBoundingBox);
        }
    }
    renderLayers() {
        var _a, _b;
        if (Object.keys(this.state).length === 0) {
            return [];
        }
        const [minX, minY] = this.props.frame.origin;
        const center = (_a = this.props.frame.rotPoint) !== null && _a !== void 0 ? _a : [minX, minY];
        const rotatingModelMatrix = getModelMatrix((_b = this.props.frame.rotDeg) !== null && _b !== void 0 ? _b : 0, center[0], center[1]);
        const isMesh = typeof this.props.meshUrl !== "undefined" &&
            this.props.meshUrl !== "";
        const isModelMatrix = typeof this.props.modelMatrix !== "undefined" &&
            this.props.modelMatrix !== null;
        if (isModelMatrix) {
            rotatingModelMatrix.multiplyRight(this.props.modelMatrix);
        }
        const layer = new privateMapLayer(this.getSubLayerProps({
            mesh: this.state["mesh"],
            meshLines: this.state["mesh_lines"],
            pickable: this.props.pickable,
            modelMatrix: rotatingModelMatrix,
            contours: this.props.contours,
            gridLines: this.props.gridLines,
            isContoursDepth: !isMesh ? false : this.props.isContoursDepth,
            colorMapName: this.props.colorMapName,
            colorMapRange: this.props.colorMapRange,
            colorMapClampColor: this.props.colorMapClampColor,
            colorMapFunction: this.props.colorMapFunction,
            propertyValueRange: this.state["propertyValueRange"],
            material: this.props.material,
            smoothShading: this.props.smoothShading,
            depthTest: this.props.depthTest,
        }));
        return [layer];
    }
}
MapLayer.layerName = "MapLayer";
MapLayer.defaultProps = layersDefaultProps["MapLayer"];
//# sourceMappingURL=mapLayer.js.map