"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module ElementGeometry
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.appendTextAnnotationGeometry = appendTextAnnotationGeometry;
const core_common_1 = require("@itwin/core-common");
const core_geometry_1 = require("@itwin/core-geometry");
const core_bentley_1 = require("@itwin/core-bentley");
const TextBlockGeometry_1 = require("./TextBlockGeometry");
const FrameGeometry_1 = require("./FrameGeometry");
const LeaderGeometry_1 = require("./LeaderGeometry");
/** Constructs the TextBlockGeometry and frame geometry and appends the geometry to the provided builder.
 * @returns true if the geometry was successfully appended.
 * @beta
 */
function appendTextAnnotationGeometry(props) {
    const annotation = core_common_1.TextAnnotation.fromJSON(props.annotationProps);
    const transform = annotation.computeTransform(props.layout.range, props.scaleFactor);
    let result = true;
    // Construct the TextBlockGeometry
    const params = new core_common_1.GeometryParams(props.categoryId, props.subCategoryId);
    const entries = (0, TextBlockGeometry_1.produceTextBlockGeometry)(props.layout, transform.clone());
    result = result && props.builder.appendTextBlock(entries, params);
    // Construct the frame geometry
    if (props.textStyleResolver.blockSettings.frame.shape !== "none") {
        result = result && (0, FrameGeometry_1.appendFrameToBuilder)(props.builder, props.textStyleResolver.blockSettings.frame, props.layout.range, transform.clone(), params);
    }
    // Construct the leader geometry
    if (annotation.leaders && annotation.leaders.length > 0) {
        result = result && (0, LeaderGeometry_1.appendLeadersToBuilder)(props.builder, annotation.leaders, props.layout, transform.clone(), params, props.textStyleResolver, props.scaleFactor);
    }
    // Construct the debug geometry
    if (props.wantDebugGeometry) {
        result = result && debugAnchorPoint(props.builder, annotation, props.layout, transform.clone());
        result = result && debugRunLayout(props.builder, props.layout, transform.clone());
        if (props.textStyleResolver.blockSettings.frame.shape !== "none")
            result = result && debugSnapPoints(props.builder, props.textStyleResolver.blockSettings, props.layout.range, transform.clone());
    }
    return result;
}
;
/**
 * Draws the anchor point and margins of the text annotation.
 * The anchor point is the point around which the text rotates and is drawn as a blue x (1m by 1m).
 * The margins are drawn as a blue box.
 * The text range is drawn as a red box.
 */
function debugAnchorPoint(builder, annotation, layout, transform) {
    const range = core_geometry_1.Range2d.fromJSON(layout.range);
    const debugAnchorPt = transform.multiplyPoint3d(annotation.computeAnchorPoint(range));
    // Make it blue
    const blueLineParams = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
    blueLineParams.lineColor = core_common_1.ColorDef.blue;
    let result = builder.appendGeometryParamsChange(blueLineParams);
    // Draw a blue box to show the element's margin
    const marginCorners = range.corners3d(true);
    transform.multiplyPoint3dArrayInPlace(marginCorners);
    result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(marginCorners));
    // Draw a blue x to show the anchor point - Rotation occurs around this point. The x will be 1 m by 1 m.
    result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(debugAnchorPt.plusXYZ(-1, -1), debugAnchorPt.plusXYZ(1, 1)));
    result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(debugAnchorPt.plusXYZ(1, -1), debugAnchorPt.plusXYZ(-1, 1)));
    // Draw a red box to show the text range
    const redLineParams = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
    redLineParams.lineColor = core_common_1.ColorDef.red;
    result = result && builder.appendGeometryParamsChange(redLineParams);
    const rangeCorners = layout.textRange.corners3d(true);
    transform.multiplyPoint3dArrayInPlace(rangeCorners);
    result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(rangeCorners));
    return result;
}
/** Draws the interval points defined by calling [[computeIntervalPoints]]. The points are shown as black dots 5x larger than the borderWeight */
function debugSnapPoints(builder, style, range, transform) {
    if (style.frame.shape === "none")
        return false;
    const points = (0, FrameGeometry_1.computeIntervalPoints)({ frame: style.frame.shape, range, transform, lineIntervalFactor: 0.5, arcIntervalFactor: 0.25 });
    const params = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
    params.lineColor = core_common_1.ColorDef.black;
    params.weight = style.frame.borderWeight * 5; // We want the dots to be bigger than the frame so we can see them.
    params.fillDisplay = core_common_1.FillDisplay.Always;
    const result = builder.appendGeometryParamsChange(params) && builder.appendGeometryQuery(core_geometry_1.PointString3d.create(points));
    return result;
}
/**
 * Draws debug geometry for each line and run in a TextBlockLayout.
 *
 * For each line and run, this function draws boxes to visualize their layout and boundaries.
 * Different run types (e.g., text, linebreak, fraction, tab) are assigned distinct colors for clarity.
 * This is useful for debugging text layout and alignment issues.
 *
 * @param builder - The geometry builder to append debug geometry to.
 * @param layout - The text block layout containing lines and runs to visualize.
 * @param documentTransform - The transform to apply to the entire document.
 * @returns True if all debug geometry was successfully appended.
 */
function debugRunLayout(builder, layout, documentTransform) {
    let result = true; // Tracks if all geometry was appended successfully
    let lastColor = core_common_1.ColorDef.black; // Last color used, to minimize param changes
    // Map run types to debug colors
    const colors = {
        "text": core_common_1.ColorDef.fromString("orange"),
        "linebreak": core_common_1.ColorDef.fromString("yellow"),
        "fraction": core_common_1.ColorDef.fromString("green"),
        "tab": core_common_1.ColorDef.fromString("aquamarine"),
        "field": core_common_1.ColorDef.fromString("purple"),
        "marker": core_common_1.ColorDef.fromString("pink"),
    };
    const drawBox = (run, lineTransform, newColor) => {
        // Only change geometry params if the color changes
        if (lastColor !== newColor) {
            const colorParams = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
            colorParams.lineColor = newColor;
            colorParams.weight = run.source.type === "linebreak" ? 3 : undefined;
            result = result && builder.appendGeometryParamsChange(colorParams);
            lastColor = newColor;
        }
        // Apply the line's offset to the run's offset
        const runTrans = core_geometry_1.Transform.createTranslationXYZ(run.offsetFromLine.x, run.offsetFromLine.y, 0);
        lineTransform.multiplyTransformTransform(runTrans, runTrans);
        // Draw the enclosing range for the run
        const runCorners = run.range.corners3d(true);
        runTrans.multiplyPoint3dArrayInPlace(runCorners);
        result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(runCorners));
    };
    layout.lines.forEach(line => {
        // Apply the line's offset transform
        const lineTrans = core_geometry_1.Transform.createTranslationXYZ(line.offsetFromDocument.x, line.offsetFromDocument.y, 0);
        documentTransform.multiplyTransformTransform(lineTrans, lineTrans);
        if (line.marker) {
            drawBox(line.marker, lineTrans, colors.marker);
        }
        line.runs.forEach(run => {
            // Determine color for this run type
            const color = colors[run.source.type] ?? core_common_1.ColorDef.black;
            drawBox(run, lineTrans, color);
        });
    });
    return result;
}
//# sourceMappingURL=TextAnnotationGeometry.js.map