import { COORDINATE_SYSTEM, Layer, project32, picking } from "@deck.gl/core";
import { lighting } from "@luma.gl/shadertools";
import { Model, Geometry } from "@luma.gl/engine";
import { phongMaterial } from "../shader_modules/phong-lighting/phong-material";
import { precisionForTests } from "../shader_modules/test-precision/precisionForTests";
import { decodeIndexFromRGB, utilities } from "../shader_modules";
import { createPropertyData } from "../utils/layerTools";
import { getImageData, } from "../utils/colormapTools";
import fs from "./map.fs.glsl";
import vs from "./map.vs.glsl";
import fsLineShader from "./line.fs.glsl";
import vsLineShader from "./line.vs.glsl";
const defaultProps = {
    data: ["dummy"],
    contours: [-1, -1],
    isContoursDepth: true,
    gridLines: false,
    colormapName: "",
    coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
    propertyValueRange: [0.0, 1.0],
    meshValueRange: [0.0, 1.0],
    depthTest: true,
    ZIncreasingDownwards: true,
    enableLighting: true,
};
// This is a private layer used only by the composite MapLayer
export default class PrivateMapLayer extends Layer {
    get isLoaded() {
        var _a;
        return (_a = this.state["isLoaded"]) !== null && _a !== void 0 ? _a : false;
    }
    setShaderModuleProps(args) {
        super.setShaderModuleProps(Object.assign(Object.assign({}, args), { lighting: Object.assign(Object.assign({}, args["lighting"]), { enabled: this.props.enableLighting }) }));
    }
    initializeState(context) {
        const gl = context.device;
        const [mesh_model, mesh_lines_model] = this._getModels(gl);
        this.setState({
            models: [mesh_model, mesh_lines_model],
            isLoaded: false,
        });
    }
    shouldUpdateState({ props, oldProps, context, changeFlags, }) {
        return (super.shouldUpdateState({
            props,
            oldProps,
            context,
            changeFlags,
        }) || changeFlags.propsOrDataChanged);
    }
    updateState({ context }) {
        this.initializeState(context);
    }
    _getModels(device) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        const colormap = device.createTexture({
            sampler: {
                addressModeU: "clamp-to-edge",
                addressModeV: "clamp-to-edge",
                minFilter: "linear",
                magFilter: "linear",
            },
            width: 256,
            height: 1,
            format: "rgb8unorm-webgl",
            data: getImageData((_a = this.props.colormapFunction) !== null && _a !== void 0 ? _a : {
                colormapName: this.props.colormapName,
                colorTables: this.context.userData
                    .colorTables,
            }),
        });
        // MESH MODEL
        const contourReferencePoint = (_b = this.props.contours[0]) !== null && _b !== void 0 ? _b : -1.0;
        const contourInterval = (_c = this.props.contours[1]) !== null && _c !== void 0 ? _c : -1.0;
        const isContoursDepth = this.props.isContoursDepth;
        const valueRangeMin = (_d = this.props.propertyValueRange[0]) !== null && _d !== void 0 ? _d : 0.0;
        const valueRangeMax = (_e = this.props.propertyValueRange[1]) !== null && _e !== void 0 ? _e : 1.0;
        // If specified color map will extend from colormapRangeMin to colormapRangeMax.
        // Otherwise it will extend from valueRangeMin to valueRangeMax.
        const colormapRangeMin = (_g = (_f = this.props.colormapRange) === null || _f === void 0 ? void 0 : _f[0]) !== null && _g !== void 0 ? _g : valueRangeMin;
        const colormapRangeMax = (_j = (_h = this.props.colormapRange) === null || _h === void 0 ? void 0 : _h[1]) !== null && _j !== void 0 ? _j : valueRangeMax;
        const isClampColor = this.props.colormapClampColor !== undefined &&
            this.props.colormapClampColor !== true &&
            this.props.colormapClampColor !== false;
        let colormapClampColor = isClampColor
            ? this.props.colormapClampColor
            : [0, 0, 0];
        // Normalize to [0,1] range.
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        colormapClampColor = colormapClampColor.map((x) => (x !== null && x !== void 0 ? x : 0) / 255);
        const isColormapClampColorTransparent = this.props.colormapClampColor === false;
        const smoothShading = this.props.normals.length == 0 ? false : this.props.smoothShading;
        const mesh_model = new Model(this.context.device, Object.assign(Object.assign({ id: `${this.props.id}-mesh` }, this.getShaders()), { geometry: new Geometry({
                topology: "triangle-list",
                attributes: Object.assign(Object.assign({ positions: { value: this.props.positions, size: 3 } }, (this.props.normals.length > 0 && {
                    normals: { value: this.props.normals, size: 3 },
                })), { properties: { value: this.props.vertexProperties, size: 1 } }),
                indices: { value: this.props.triangleIndices, size: 1 },
            }), bufferLayout: this.getAttributeManager().getBufferLayouts(), bindings: {
                colormap: colormap,
            }, isInstanced: false }));
        mesh_model.shaderInputs.setProps({
            map: {
                contourReferencePoint,
                contourInterval,
                isContoursDepth,
                valueRangeMin,
                valueRangeMax,
                colormapRangeMin,
                colormapRangeMax,
                colormapClampColor,
                isColormapClampColorTransparent,
                isClampColor,
                smoothShading,
                ZIncreasingDownwards: this.props.ZIncreasingDownwards,
            },
        });
        // MESH LINES
        const mesh_lines_model = new Model(device, Object.assign(Object.assign({ id: `${this.props.id}-lines` }, super.getShaders({
            vs: vsLineShader,
            fs: fsLineShader,
            modules: [project32, picking, mapUniforms, precisionForTests],
        })), { geometry: new Geometry({
                topology: "line-list",
                attributes: {
                    positions: { value: this.props.positions, size: 3 },
                },
                indices: { value: this.props.lineIndices, size: 1 },
            }), bufferLayout: this.getAttributeManager().getBufferLayouts(), isInstanced: false }));
        mesh_lines_model.shaderInputs.setProps({
            map: {
                contourReferencePoint,
                contourInterval,
                isContoursDepth,
                valueRangeMin,
                valueRangeMax,
                colormapRangeMin,
                colormapRangeMax,
                colormapClampColor,
                isColormapClampColorTransparent,
                isClampColor,
                smoothShading,
                ZIncreasingDownwards: this.props.ZIncreasingDownwards,
            },
        });
        return [mesh_model, mesh_lines_model];
    }
    draw(args) {
        if (!this.state["models"]) {
            return;
        }
        const { context } = args;
        const { gl } = context;
        const [mesh_model, mesh_lines_model] = this.state["models"];
        gl.enable(gl.POLYGON_OFFSET_FILL);
        if (!this.props.depthTest) {
            gl.disable(gl.DEPTH_TEST);
        }
        gl.polygonOffset(1, 1);
        mesh_model.draw(context.renderPass);
        gl.disable(gl.POLYGON_OFFSET_FILL);
        if (!this.props.depthTest) {
            gl.enable(gl.DEPTH_TEST);
        }
        if (this.props.gridLines) {
            mesh_lines_model.draw(context.renderPass);
        }
        if (!this.state["isLoaded"]) {
            this.setState(Object.assign(Object.assign({}, this.state), { isLoaded: true }));
        }
    }
    decodePickingColor() {
        return 0;
    }
    getPickingInfo({ info }) {
        var _a;
        if (!info.color) {
            return info;
        }
        const layer_properties = [];
        // Note these colors are in the  0-255 range.
        const [r, g, b] = info.color;
        const vertexIndex = decodeIndexFromRGB([r, g, b]);
        if (typeof ((_a = info.coordinate) === null || _a === void 0 ? void 0 : _a[2]) !== "undefined") {
            const zScale = this.props.modelMatrix
                ? this.props.modelMatrix[10]
                : 1;
            const depth = (this.props.ZIncreasingDownwards
                ? -info.coordinate[2]
                : info.coordinate[2]) / Math.max(0.001, zScale);
            layer_properties.push(createPropertyData("Depth", depth));
        }
        const properties = this.props.vertexProperties;
        const property = properties[vertexIndex];
        layer_properties.push(createPropertyData("Property", property));
        return Object.assign(Object.assign({}, info), { properties: layer_properties });
    }
    getShaders() {
        return super.getShaders({
            vs,
            fs,
            modules: [
                project32,
                picking,
                utilities,
                lighting,
                phongMaterial,
                mapUniforms,
                precisionForTests,
            ],
        });
    }
}
PrivateMapLayer.layerName = "privateMapLayer";
PrivateMapLayer.defaultProps = defaultProps;
// local shader module for the uniforms
const mapUniformsBlock = /*glsl*/ `\
uniform mapUniforms {
    bool isContoursDepth;
    float contourReferencePoint;
    float contourInterval;

    float valueRangeMin;
    float valueRangeMax;
    float colormapRangeMin;
    float colormapRangeMax;

    vec3 colormapClampColor;
    bool isClampColor;
    bool isColormapClampColorTransparent;
    bool smoothShading;
    bool ZIncreasingDownwards;
} map;
`;
// NOTE: this must exactly the same name as in the uniform block
const mapUniforms = {
    name: "map",
    vs: mapUniformsBlock,
    fs: mapUniformsBlock,
    uniformTypes: {
        isContoursDepth: "u32",
        contourReferencePoint: "f32",
        contourInterval: "f32",
        valueRangeMin: "f32",
        valueRangeMax: "f32",
        colormapRangeMin: "f32",
        colormapRangeMax: "f32",
        colormapClampColor: "vec3<f32>",
        isClampColor: "u32",
        isColormapClampColorTransparent: "u32",
        smoothShading: "u32",
        ZIncreasingDownwards: "u32",
    },
};
//# sourceMappingURL=privateMapLayer.js.map