import { COORDINATE_SYSTEM, Layer, picking, project32 } from "@deck.gl/core";
import { GL } from "@luma.gl/constants";
import { Geometry, Model } from "@luma.gl/engine";
import { lighting } from "@luma.gl/shadertools";
import { phongMaterial } from "../shader_modules/phong-lighting/phong-material";
import { precisionForTests } from "../shader_modules/test-precision/precisionForTests";
import { createPropertyData } from "../utils/layerTools";
import fsShader from "./triangle.fs.glsl";
import vsShader from "./triangle.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,
    color: [100, 100, 255],
    coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
    depthTest: true,
    smoothShading: true,
    ZIncreasingDownwards: true,
    enableLighting: true,
};
// This is a private layer used only by the composite TriangleLayer
export default class PrivateTriangleLayer 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 [triangleModel, lineModel] = this._getModels(gl);
        this.setState({ models: [triangleModel, lineModel], isLoaded: false });
    }
    shouldUpdateState({ props, oldProps, context, changeFlags, }) {
        return (super.shouldUpdateState({
            props,
            oldProps,
            context,
            changeFlags,
        }) || changeFlags.propsOrDataChanged);
    }
    updateState({ context }) {
        this.initializeState(context);
    }
    _getModels(device) {
        const triangleModel = new Model(device, Object.assign(Object.assign({ id: `${this.props.id}-mesh` }, super.getShaders({
            vs: vsShader,
            fs: fsShader,
            modules: [
                project32,
                picking,
                lighting,
                phongMaterial,
                trianglesUniforms,
                precisionForTests,
            ],
        })), { bufferLayout: this.getAttributeManager().getBufferLayouts(), geometry: new Geometry(this.props.geometryTriangles), isInstanced: false }));
        const lineModel = new Model(device, Object.assign(Object.assign({ id: `${this.props.id}-lines` }, super.getShaders({
            vs: vsLineShader,
            fs: fsLineShader,
            modules: [
                project32,
                picking,
                triangleMeshUniforms,
                precisionForTests,
            ],
        })), { bufferLayout: this.getAttributeManager().getBufferLayouts(), geometry: new Geometry(this.props.geometryLines), isInstanced: false }));
        return [triangleModel, lineModel];
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    draw(args) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        if (!this.state["models"]) {
            return;
        }
        const { gl } = args.context;
        const [triangleModel, lineModel] = this.state["models"];
        if (!this.props.depthTest) {
            gl.disable(GL.DEPTH_TEST);
        }
        gl.enable(GL.POLYGON_OFFSET_FILL);
        gl.polygonOffset(1, 1);
        triangleModel.shaderInputs.setProps(Object.assign(Object.assign({}, args.uniforms), { triangles: {
                isContoursDepth: defaultProps.isContoursDepth,
                contourReferencePoint: (_b = (_a = this.props.contours) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : defaultProps.contours[0],
                contourInterval: (_d = (_c = this.props.contours) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : defaultProps.contours[1],
                // Normalize to [0,1] range.
                uColor: [
                    ...((_e = this.props.color) !== null && _e !== void 0 ? _e : defaultProps.color).map((x) => (x !== null && x !== void 0 ? x : 0) / 255),
                    1 /* alpha channel */,
                ],
                smoothShading: (_f = this.props.smoothShading) !== null && _f !== void 0 ? _f : defaultProps.smoothShading,
                ZIncreasingDownwards: (_g = this.props.ZIncreasingDownwards) !== null && _g !== void 0 ? _g : defaultProps.ZIncreasingDownwards,
            } }));
        triangleModel.draw(args.context.renderPass);
        gl.disable(GL.POLYGON_OFFSET_FILL);
        if (this.props.gridLines) {
            lineModel.shaderInputs.setProps(Object.assign(Object.assign({}, args.uniforms), { triangleMesh: {
                    ZIncreasingDownwards: (_h = this.props.ZIncreasingDownwards) !== null && _h !== void 0 ? _h : defaultProps.ZIncreasingDownwards,
                } }));
            lineModel.draw(args.context.renderPass);
        }
        if (!this.props.depthTest) {
            gl.enable(GL.DEPTH_TEST);
        }
        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 = [];
        const zScale = this.props.modelMatrix ? this.props.modelMatrix[10] : 1;
        if (typeof ((_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));
        }
        return Object.assign(Object.assign({}, info), { properties: layer_properties });
    }
}
PrivateTriangleLayer.layerName = "privateTriangleLayer";
PrivateTriangleLayer.defaultProps = defaultProps;
const triangleMeshUniformsBlock = `\
uniform triangleMeshUniforms {
    uniform bool ZIncreasingDownwards;
} triangleMesh;
`;
// NOTE: this must exactly the same name than in the uniform block
const triangleMeshUniforms = {
    name: "triangleMesh",
    vs: triangleMeshUniformsBlock,
    fs: undefined,
    uniformTypes: {
        ZIncreasingDownwards: "f32",
    },
};
const triangleUniformsBlock = /*glsl*/ `\
uniform trianglesUniforms {
    uniform bool isContoursDepth;
    uniform float contourReferencePoint;
    uniform float contourInterval;
    uniform vec4 uColor;
    uniform bool smoothShading;
    uniform bool ZIncreasingDownwards;
} triangles;
`;
// NOTE: this must exactly the same name than in the uniform block
const trianglesUniforms = {
    name: "triangles",
    vs: triangleUniformsBlock,
    fs: triangleUniformsBlock,
    uniformTypes: {
        isContoursDepth: "u32",
        contourReferencePoint: "f32",
        contourInterval: "f32",
        uColor: "vec4<f32>",
        smoothShading: "u32",
        ZIncreasingDownwards: "u32",
    },
};
//# sourceMappingURL=privateTriangleLayer.js.map