/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { h, Host, } from "@stencil/core";
import { Matrix4 } from "@vertexvis/geometry";
import { MultiElementInteractionHandler } from "../../lib/interactions/multiElementInteractionHandler";
import { Viewport } from "../../lib/types";
import { Renderer2d, update2d } from "./renderer2d";
import { Renderer3d, update3d } from "./renderer3d";
/**
 * The `ViewerDomRenderer` is responsible for managing a
 * `<vertex-viewer-dom-renderer>` element. This element supports drawing DOM
 * objects in a local 3D scene that is synced with a remote rendered scene.
 */
export class ViewerDomRenderer {
    constructor() {
        /**
         * Specifies the drawing mode for the renderer.
         *
         * When in `3d` mode, elements are positioned using CSS 3D transforms and will
         * scale and rotate with the camera. In `2d` mode, a simpler 2D transform is
         * used, and elements will not scale or rotate with camera changes.
         */
        this.drawMode = '3d';
        /**
         * Specifies whether to propagate events to the viewer's interaction handlers
         *
         * When `true` this <vertex-viewer-dom-renderer> will be registered as a valid event target
         * for the viewer. This enables camera interactions to be initiated from elements within this renderer.
         *
         * When `false` this <vertex-viewer-dom-renderer> will *not* be registered as a target
         * for the viewer.
         */
        this.propagateEventsToViewer = true;
        this.viewport = new Viewport(0, 0);
        this.invalidateFrameCounter = 0;
        this.interactionDisposables = [];
        this.handleViewerFrameDrawn = async () => {
            this.updatePropsFromViewer();
        };
    }
    /**
     * @ignore
     */
    componentWillLoad() {
        var _a;
        const resized = new ResizeObserver(() => this.handleResize());
        resized.observe(this.hostEl);
        const mutation = new MutationObserver(() => this.handleChildrenChange());
        mutation.observe(this.hostEl, { childList: true });
        this.handleViewerChange(this.viewer, undefined);
        if (((_a = this.viewer) === null || _a === void 0 ? void 0 : _a.frame) != null) {
            this.handleViewerFrameDrawn();
        }
    }
    /**
     * @ignore
     */
    render() {
        if (this.camera != null) {
            if (this.drawMode === '2d') {
                return (h(Host, null, h(Renderer2d, null, h("slot", null))));
            }
            else {
                return (h(Host, null, h(Renderer3d, { camera: this.camera, viewport: this.viewport }, h("slot", null))));
            }
        }
        else {
            return h(Host, null);
        }
    }
    /**
     * @ignore
     */
    componentWillRender() {
        this.updateElements();
    }
    /**
     * @ignore
     */
    handleViewerChange(newViewer, oldViewer) {
        oldViewer === null || oldViewer === void 0 ? void 0 : oldViewer.removeEventListener('frameDrawn', this.handleViewerFrameDrawn);
        newViewer === null || newViewer === void 0 ? void 0 : newViewer.addEventListener('frameDrawn', this.handleViewerFrameDrawn);
        if (this.propagateEventsToViewer && newViewer != null) {
            this.handleEventPropagationToViewer(newViewer);
        }
    }
    /**
     * @ignore
     */
    handlePropertyChange() {
        this.invalidateFrame();
    }
    invalidateFrame() {
        this.invalidateFrameCounter = this.invalidateFrameCounter + 1;
    }
    /**
     * disposes any existing disposables, and registers new handlers on the newly provided viewer.
     * @param newViewer
     */
    handleEventPropagationToViewer(newViewer) {
        this.interactionDisposables.forEach((disposable) => {
            disposable.dispose();
        });
        this.interactionDisposables = [];
        newViewer.getInteractionHandlers().then((handlers) => {
            handlers.forEach((handler) => {
                if (handler instanceof MultiElementInteractionHandler) {
                    const disposable = handler.registerAdditionalElement(this.hostEl);
                    this.interactionDisposables = [
                        ...this.interactionDisposables,
                        disposable,
                    ];
                }
            });
        });
    }
    async updateElements() {
        const { viewport, camera } = this;
        const worldMatrix = Matrix4.makeIdentity();
        if (camera != null) {
            if (this.drawMode === '3d') {
                update3d(this.hostEl, worldMatrix, viewport, camera, this.depthBuffer);
            }
            else {
                update2d(this.hostEl, worldMatrix, viewport, camera, this.depthBuffer);
            }
        }
    }
    handleResize() {
        const bounds = this.hostEl.getBoundingClientRect();
        this.viewport = new Viewport(bounds.width, bounds.height);
    }
    handleChildrenChange() {
        this.invalidateFrame();
    }
    async updatePropsFromViewer() {
        const { frame } = this.viewer || {};
        this.depthBuffer = await (frame === null || frame === void 0 ? void 0 : frame.depthBuffer());
        this.camera = frame === null || frame === void 0 ? void 0 : frame.scene.camera;
    }
    static get is() { return "vertex-viewer-dom-renderer"; }
    static get encapsulation() { return "scoped"; }
    static get originalStyleUrls() {
        return {
            "$": ["viewer-dom-renderer.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["viewer-dom-renderer.css"]
        };
    }
    static get properties() {
        return {
            "drawMode": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "ViewerDomRendererDrawMode",
                    "resolved": "\"2d\" | \"3d\"",
                    "references": {
                        "ViewerDomRendererDrawMode": {
                            "location": "local",
                            "path": "/home/runner/work/vertex-web-sdk/vertex-web-sdk/packages/viewer/src/components/viewer-dom-renderer/viewer-dom-renderer.tsx",
                            "id": "src/components/viewer-dom-renderer/viewer-dom-renderer.tsx::ViewerDomRendererDrawMode"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies the drawing mode for the renderer.\n\nWhen in `3d` mode, elements are positioned using CSS 3D transforms and will\nscale and rotate with the camera. In `2d` mode, a simpler 2D transform is\nused, and elements will not scale or rotate with camera changes."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "draw-mode",
                "defaultValue": "'3d'"
            },
            "propagateEventsToViewer": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies whether to propagate events to the viewer's interaction handlers\n\nWhen `true` this <vertex-viewer-dom-renderer> will be registered as a valid event target\nfor the viewer. This enables camera interactions to be initiated from elements within this renderer.\n\nWhen `false` this <vertex-viewer-dom-renderer> will *not* be registered as a target\nfor the viewer."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "propagate-events-to-viewer",
                "defaultValue": "true"
            },
            "viewer": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "HTMLVertexViewerElement",
                    "resolved": "HTMLVertexViewerElement | undefined",
                    "references": {
                        "HTMLVertexViewerElement": {
                            "location": "global",
                            "id": "global::HTMLVertexViewerElement"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The viewer synced to this renderer. This property will automatically be\nassigned if the renderer is a child of `<vertex-viewer>`."
                },
                "getter": false,
                "setter": false
            },
            "camera": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "FrameCameraBase",
                    "resolved": "FrameCameraBase | undefined",
                    "references": {
                        "FrameCameraBase": {
                            "location": "import",
                            "path": "../../lib/types/frame",
                            "id": "src/lib/types/frame.ts::FrameCameraBase",
                            "referenceLocation": "FrameCameraBase"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The current camera of the frame.\n\nThis property will automatically be set when supplying a viewer to the\ncomponent, or when added as a child to `<vertex-viewer>`."
                },
                "getter": false,
                "setter": false
            },
            "depthBuffer": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "DepthBuffer",
                    "resolved": "DepthBuffer | undefined",
                    "references": {
                        "DepthBuffer": {
                            "location": "import",
                            "path": "../../lib/types",
                            "id": "src/lib/types/index.ts::DepthBuffer",
                            "referenceLocation": "DepthBuffer"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The current depth buffer of the frame.\n\nThis property will automatically be set when supplying a viewer to the\ncomponent, or when added as a child to `<vertex-viewer>`."
                },
                "getter": false,
                "setter": false
            }
        };
    }
    static get states() {
        return {
            "viewport": {},
            "invalidateFrameCounter": {},
            "interactionDisposables": {}
        };
    }
    static get elementRef() { return "hostEl"; }
    static get watchers() {
        return [{
                "propName": "viewer",
                "methodName": "handleViewerChange"
            }];
    }
    static get listeners() {
        return [{
                "name": "propertyChange",
                "method": "handlePropertyChange",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
//# sourceMappingURL=viewer-dom-renderer.js.map
