"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FeatureGraphicsRenderer = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const core_geometry_1 = require("@itwin/core-geometry");
const internal_1 = require("../../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
 */
class FeatureGraphicsRenderer extends internal_1.FeatureGeometryBaseRenderer {
    hasSymbologyRenderer() { return false; }
    constructor(props) {
        super();
        this._scratchPointsArray = new core_geometry_1.GrowableXYZArray();
        this._scratchPaths = [];
        this._graphics = [];
        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(core_geometry_1.Loop.create(core_geometry_1.LineString3d.create(pointsArray)));
            }
            const mergedLoops = core_geometry_1.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: core_geometry_1.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 (error) {
                core_bentley_1.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) => core_common_1.Cartographic.fromDegrees({
                longitude: this._crs === "webMercator" ? internal_1.WebMercator.getEPSG4326Lon(pt.x) : pt.x,
                latitude: this._crs === "webMercator" ? internal_1.WebMercator.getEPSG4326Lat(pt.y) : pt.y,
                height: pt.z,
            }));
            return bgMapGeom.cartographicToDbFromWgs84Gcs(cartoPts);
        }
        return [];
    }
}
exports.FeatureGraphicsRenderer = FeatureGraphicsRenderer;
//# sourceMappingURL=FeatureGraphicsRenderer.js.map