///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2026, Open Design Alliance (the "Alliance").
// All rights reserved.
// 
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
// 
//   This application incorporates Open Design Alliance software pursuant to a
//   license agreement with Open Design Alliance.
//   Open Design Alliance Copyright (C) 2002-2026 by Open Design Alliance.
//   All rights reserved.
// 
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////

import { ModelImpl, Loader, loaders } from '@inweb/viewer-three';
import { Potree, PointColorType, PointSizeType, PointShape } from 'potree-core';
import { Info } from '@inweb/viewer-core';

class PotreeModelImpl extends ModelImpl {
    getInfo() {
        var _a, _b;
        let totalPoints = 0;
        let totalNodes = 0;
        let loadedGeometryBytes = 0;
        let estimatedTotalGeometryBytes = 0;
        let geometryBytes = 0;
        const bytesPerPoint = ((_b = (_a = this.pco.pcoGeometry) === null || _a === void 0 ? void 0 : _a.pointAttributes) === null || _b === void 0 ? void 0 : _b.byteSize) || 0;
        if (this.pco.pcoGeometry && this.pco.pcoGeometry.root) {
            this.pco.pcoGeometry.root.traverse((node) => {
                totalNodes++;
                const numPoints = node.numPoints || 0;
                totalPoints += numPoints;
                if (node.loaded && node.geometry) {
                    if (node.geometry.attributes) {
                        for (const name in node.geometry.attributes) {
                            const attribute = node.geometry.attributes[name];
                            if (attribute && attribute.array) {
                                loadedGeometryBytes += attribute.array.byteLength;
                            }
                        }
                    }
                    if (node.geometry.index && node.geometry.index.array) {
                        loadedGeometryBytes += node.geometry.index.array.byteLength;
                    }
                }
                if (bytesPerPoint > 0 && numPoints > 0) {
                    estimatedTotalGeometryBytes += numPoints * (bytesPerPoint * 2 - 1);
                }
            }, true);
        }
        geometryBytes = Math.max(loadedGeometryBytes, estimatedTotalGeometryBytes);
        const info = new Info();
        info.scene.objects = totalNodes;
        info.scene.points = totalPoints;
        info.scene.triangles = 0;
        info.scene.lines = 0;
        info.scene.edges = 0;
        info.memory.geometries = totalNodes;
        info.memory.geometryBytes = Math.floor(geometryBytes);
        info.memory.textures = 0;
        info.memory.textureBytes = 0;
        info.memory.materials = 1;
        info.memory.totalEstimatedGpuBytes = Math.floor(geometryBytes);
        info.optimizedScene.objects = info.scene.objects;
        info.optimizedScene.triangles = info.scene.triangles;
        info.optimizedScene.points = info.scene.points;
        info.optimizedScene.lines = info.scene.lines;
        info.optimizedScene.edges = info.scene.edges;
        return info;
    }
    getExtents(target) {
        return target.union(this.pco.pcoGeometry.boundingBox);
    }
}

class PotreeFileLoader extends Loader {
    constructor(viewer) {
        super();
        this.updatePointClouds = () => {
            const result = this.potree.updatePointClouds(this.pointClouds, this.viewer.camera, this.viewer.renderer);
            if (result.exceededMaxLoadsToGPU || result.nodeLoadPromises.length > 0)
                this.viewer.update();
        };
        this.viewer = viewer;
        this.potree = new Potree();
        this.pointClouds = [];
        this.viewer.addEventListener("render", this.updatePointClouds);
        this.viewer.addEventListener("changecamera", this.updatePointClouds);
    }
    dispose() {
        this.pointClouds.forEach((pco) => pco.dispose());
        this.viewer.removeEventListener("render", this.updatePointClouds);
        this.viewer.removeEventListener("changecamera", this.updatePointClouds);
    }
    isSupport(file, format) {
        return typeof file === "string" && /(cloud.js|metadata.json)$/i.test(file);
    }
    async load(file, format, params = {}) {
        const path = (params.path || "") + file;
        const index = path.lastIndexOf("/");
        const baseUrl = path.slice(0, index + 1);
        const url = path.slice(index + 1);
        const pco = await this.potree.loadPointCloud(url, baseUrl);
        pco.material.size = 1.0;
        pco.material.shape = 2;
        pco.material.inputColorEncoding = 1;
        pco.material.outputColorEncoding = 1;
        pco.material.pointColorType = PointColorType.RGB;
        pco.material.pointSizeType = PointSizeType.ADAPTIVE;
        pco.material.shape = PointShape.CIRCLE;
        if (params.position)
            pco.position.copy(params.position);
        if (params.rotation)
            pco.rotation.copy(params.rotation);
        if (params.scale)
            pco.scale.copy(params.scale);
        this.pointClouds.push(pco);
        const modelImpl = new PotreeModelImpl(pco);
        modelImpl.id = params.modelId || this.extractFileName(file);
        modelImpl.pco = pco;
        this.viewer.scene.add(pco);
        this.viewer.models.push(modelImpl);
        this.viewer.syncOptions();
        this.viewer.syncOverlay();
        this.viewer.emitEvent({ type: "databasechunk", data: pco, file });
        this.viewer.update(true);
        return this;
    }
}

loaders.registerLoader("potree-file", (viewer) => new PotreeFileLoader(viewer));
//# sourceMappingURL=PotreeLoader.module.js.map
