/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { Logger } from "@itwin/core-bentley";
import { Cartographic } from "@itwin/core-common";
import { GrowableXYZArray, LineString3d, Loop, Point3dArray, RegionOps } from "@itwin/core-geometry";
import { FeatureGeometryBaseRenderer, WebMercator } from "../../../../tile/internal";
const loggerCategory = "MapLayerImageryProvider.FeatureGraphicsRenderer";
/** Feature geometry renderer implementation that will "render" a list of [GraphicPrimitive]($frontend)
 * This renderer initial objective is to read geometries when a call to [[MapLayerImageryProvider.getFeatureInfo]] is performed.
 * @internal
 */
export class FeatureGraphicsRenderer extends FeatureGeometryBaseRenderer {
    hasSymbologyRenderer() { return false; }
    _scratchPointsArray = new GrowableXYZArray();
    _scratchPaths = [];
    _graphics = [];
    _viewport;
    _crs;
    constructor(props) {
        super();
        this._viewport = props.viewport;
        this._crs = props.crs;
    }
    moveGraphics() {
        const graphics = this._graphics;
        this._graphics = [];
        return graphics;
    }
    beginPath() {
        this._scratchPointsArray.clear();
        this._scratchPaths = [];
    }
    closePath() {
        if (this._scratchPointsArray.length > 0) {
            this._scratchPaths.push(this._scratchPointsArray.getArray());
            this._scratchPointsArray.clear();
        }
    }
    async lineTo(x, y) {
        this._scratchPointsArray.push({ x, y, z: 0 });
    }
    async moveTo(x, y) {
        if (this._scratchPointsArray.length > 0) {
            this._scratchPaths.push(this._scratchPointsArray.getArray());
            this._scratchPointsArray.clear();
        }
        this._scratchPointsArray.push({ x, y, z: 0 });
    }
    async fill() {
        if (this._scratchPaths.length > 0) {
            const loops = [];
            const pathPromises = [];
            for (const points of this._scratchPaths) {
                pathPromises.push(this.toSpatial(points));
            }
            const pathsArray = await Promise.all(pathPromises);
            for (const pointsArray of pathsArray) {
                loops.push(Loop.create(LineString3d.create(pointsArray)));
            }
            const mergedLoops = RegionOps.constructAllXYRegionLoops(loops);
            for (const loop of mergedLoops) {
                for (const negativeLoop of loop.negativeAreaLoops) {
                    this._graphics.push({ type: "loop", loop: negativeLoop });
                }
            }
            this._scratchPaths = [];
        }
    }
    async stroke() {
        if (this._scratchPointsArray.length > 0) {
            this._scratchPaths.push(this._scratchPointsArray.getArray());
            this._scratchPointsArray.clear();
        }
        const pathPromises = [];
        for (const geoPt of this._scratchPaths) {
            pathPromises.push(this.toSpatial(geoPt));
        }
        const reprojectedPaths = await Promise.all(pathPromises);
        for (const path of reprojectedPaths) {
            this._graphics.push({ type: "linestring", points: Point3dArray.clonePoint3dArray(path) });
        }
        this._scratchPaths = [];
    }
    drawPoint(x, y) {
        this._scratchPointsArray.push({ x, y, z: 0 });
    }
    async finishPoints() {
        if (this._scratchPointsArray.length > 0) {
            // Backend reprojection
            const pointsArray = this._scratchPointsArray.getArray();
            try {
                const spatialPoints = await this.toSpatial(pointsArray);
                this._graphics.push({ type: "pointstring", points: spatialPoints });
            }
            catch {
                Logger.logError(loggerCategory, "FeatureGraphicsRenderer: Could not reproject points");
            }
            this._scratchPointsArray.clear();
        }
    }
    async toSpatial(geoPoints) {
        const bgMapGeom = this._viewport.displayStyle.getBackgroundMapGeometry();
        if (bgMapGeom) {
            const cartoPts = geoPoints.map((pt) => Cartographic.fromDegrees({
                longitude: this._crs === "webMercator" ? WebMercator.getEPSG4326Lon(pt.x) : pt.x,
                latitude: this._crs === "webMercator" ? WebMercator.getEPSG4326Lat(pt.y) : pt.y,
                height: pt.z,
            }));
            return bgMapGeom.cartographicToDbFromWgs84Gcs(cartoPts);
        }
        return [];
    }
}
//# sourceMappingURL=FeatureGraphicsRenderer.js.map