import type { Id64String } from "@itwin/core-bentley";
import type { GeometryStreamProps } from "@itwin/core-common";
import type { DecorateContext, HitDetail } from "@itwin/core-frontend";
import { BeButtonEvent } from "@itwin/core-frontend";
import type { TransformProps, XYProps, XYZProps } from "@itwin/core-geometry";
import { Point3d, Transform } from "@itwin/core-geometry";
import { Point2d } from "@itwin/core-geometry";
import type { FormatterSpec } from "@itwin/core-quantity";
import { MeasurementButtonHandledEvent } from "./MeasurementEnums.js";
import type { MeasurementProps } from "./MeasurementProps.js";
import { MeasurementViewTarget } from "./MeasurementViewTarget.js";
import { SheetMeasurementsHelper } from "./SheetMeasurementHelper.js";
/** A property value on a measurement that can be aggregated with other similarly-named properties from other measurements so aggregate totals can be displayed in the UI. */
export interface AggregatableValue {
    value: number;
    formatSpec: FormatterSpec;
}
/** Property value information to represent a value from a measurement in the UI. */
export interface WidgetValue {
    label: string;
    name: string;
    value: string;
    aggregatableValue?: AggregatableValue;
}
/** Interface for property grid data of a measurement. */
export interface MeasurementWidgetData {
    title: string;
    properties: WidgetValue[];
}
export declare namespace DrawingMetadata {
    function toJSON(obj: DrawingMetadata | undefined): DrawingMetadataProps | undefined;
    function fromJSON(json: DrawingMetadataProps): DrawingMetadata;
    function withOverrides(current: DrawingMetadata, overrides?: Partial<DrawingMetadata>): DrawingMetadata;
}
/** Abstract class for serializers that read/write measurements from JSON. */
export declare abstract class MeasurementSerializer {
    /** Gets the unique measurement name. This is the property that the serializer looks for on incoming JSON data and writes to when serializing. */
    abstract get measurementName(): string;
    /** Given a JSON object, a single or an array of Measurements is attempted to be parsed.
     * @param data JSON object or undefined.
     * @returns Single or Multiple measurements or undefined if data could not be parsed correctly.
     */
    parse(data: any): Measurement | Measurement[] | undefined;
    /** Serializes single or multiple measurements to a JSON object.
     * @param measurement Single or multiple measurements.
     * @returns JSON object that will have a single property (the measurementName) or undefined if serialization failed.
     */
    serialize(measurement: Measurement | Measurement[]): any;
    /** Determines if the measurements are all the same type. Serializers do not handle an array of differently typed measurements.
     * @param measurement One or more measurements to check
     * @returns true if all measurements are of the same type, false if otherwise.
     */
    areValidTypes(measurement: Measurement | Measurement[]): boolean;
    /** Subclasses need to implement this to do type checking.
     * @param measurement Measurement to check.
     * @returns true if the measurement is a valid type, false if otherwise.
     */
    abstract isValidType(measurement: Measurement): boolean;
    /**
     * Subclasses can implement this to do JSON data validation. Some measurements may have optional properties, other measurements may need data that HAS to be present in order to
     * create a new instance.
     * @param json JSON data to validate.
     */
    isValidJSON(_json: any): boolean;
    /** Subclasses need to implement this to handle parsing a measurement type from JSON.
     * @param data JSON data to parse.
     * @returns Measurement instance or undefined if parsing failed.
     */
    protected abstract parseSingle(data: MeasurementProps): Measurement | undefined;
    /** Handles serializing a measurement type to JSON.
     * @param measurement Measurement instance to serialize.
     * @returns JSON object with measurement props.
     */
    protected serializeSingle(measurement: Measurement): MeasurementProps | undefined;
}
/** Defines the context for testing if a measurement is being picked. */
export declare class MeasurementPickContext {
    /** Geometry ID that was picked. */
    readonly geomId: string;
    /** Optional extended information about the pick hit on the geometry. */
    readonly hitDetail?: HitDetail;
    /** Optional extended information about the button event that generated the pick. */
    readonly buttonEvent?: BeButtonEvent;
    /**
     * Constructs a new pick detail.
     * @param geomId Geometry ID that was picked.
     * @param hitDetail Optional information about the pick hit on the geometry.
     * @param ev Optional information about the button event that generated the pick.
     */
    constructor(geomId: string, hitDetail?: HitDetail, ev?: BeButtonEvent);
    /**
     * Creates a pick detail from the supplied arguments.
     * @param hitDetail HitDetail containing the pick information.
     * @param ev Button event, if undefined the current input state is queried.
     */
    static create(hitDetail: HitDetail, ev?: BeButtonEvent): MeasurementPickContext;
    /**
     * Creates a pick detail from the supplied arguments.
     * @param geomId Geometry ID that was picked
     * @param ev Button event, if undefined the current input state is queried.
     */
    static createFromSourceId(geomId: string, ev?: BeButtonEvent): MeasurementPickContext;
}
/** Represents how two measurements should be compared to in an equality test. If data-equality is desired, use some of these options to turn off checks for base properties. */
export interface MeasurementEqualityOptions {
    /** If true, ignore styling properties when comparing. */
    ignoreStyle?: true | undefined;
    /** If true, ignore view target contents when comparing. */
    ignoreViewTarget?: true | undefined;
    /** If true, ignore any ID information (grouping or otherwise). */
    ignoreIds?: true | undefined;
    /** If true, ignore the measurement labels. */
    ignoreLabel?: true | undefined;
    /** If true, ignore any other non-data state information, such as if the measurement's lock state. When combined with the other ignore options, the equality will not test base measurement properties. */
    ignoreNonDataState?: true | undefined;
    /** Tolerance for numerical equality (usually [[Geometry.smallMetricDistance]] is a default). */
    tolerance?: number;
    /** Tolerance for angle equality, if needed (usually [[Geometry.smallAngleRadians]] is a default). */
    angleTolerance?: number;
}
export interface DrawingMetadataProps extends Omit<DrawingMetadata, "origin" | "extents" | "sheetToWorldTransform"> {
    origin: XYProps;
    extents?: XYProps;
    sheetToWorldTransform?: {
        masterOrigin: XYZProps;
        sheetTov8Drawing: TransformProps;
        v8DrawingToDesign: TransformProps;
    };
}
export interface DrawingMetadata {
    /** Id of the drawing */
    drawingId?: string;
    /** Scaling from sheet to world distance */
    worldScale: number;
    /** Origin of the drawing in sheet coordinates */
    origin: Point2d;
    /** Extents of the drawing in sheet coordinates */
    extents?: Point2d;
    /** Represents the transform from sheet points to 3d points */
    sheetToWorldTransform?: SheetMeasurementsHelper.SheetTransformParams;
    /** Represents the transform from sheet points to distance along alignment (X) and vertical position related to alignment (Y) */
    sheetToProfileTransform?: Transform;
}
/** Handler function that modifies the data sent to the widget for display. */
export type MeasurementDataWidgetHandlerFunction = (m: Measurement, currentData: MeasurementWidgetData) => Promise<void>;
/** Handler for modifying the data sent to the widget for display. The highest priority will execute last. */
export interface MeasurementDataWidgetHandler {
    priority: number;
    handlerFunction: MeasurementDataWidgetHandlerFunction;
}
/**
 * Abstract class representing a Measurement. Measurements are semi-persistent annotation objects that can be drawn to a viewport. They are not stored
 * in the iModel database, but can be serialized to a JSON string for storage.
 */
export declare abstract class Measurement {
    private static _serializers;
    private static _dataForMeasurementWidgetHandlers;
    private _isLocked;
    private _groupId?;
    private _subgroupId?;
    private _id?;
    private _label?;
    private _style?;
    private _lockStyle?;
    private _viewTarget;
    private _displayLabels;
    private _transientId?;
    private _isVisible;
    private _drawingMetadata?;
    /** Default drawing style name. */
    static readonly defaultStyle: string;
    /** Default locked drawing styl name. */
    static readonly defaultLockStyle: string;
    /** Each subclass should register and set a serializer object for itself to this property. If undefined, the measurement does not participate in serialization. */
    static readonly serializer: MeasurementSerializer | undefined;
    /** Gets the serializer associated with this measurement type. If undefined, the measurement does not participate in serialization. */
    get serializer(): MeasurementSerializer | undefined;
    /** Gets or sets the transient ID used by this measurement. This enables using measurements with selection, snapping, and picking.
     * Subclasses should get a transient ID when needed from the imodel in the global @see [[MeasurementSelectionSet]]. If the imodel
     * changes, the transient ID of all measurements is reset. Normally you do not need to do this yourself.
     */
    get transientId(): Id64String | undefined;
    set transientId(newId: Id64String | undefined);
    get drawingMetadata(): Readonly<DrawingMetadata | undefined>;
    set drawingMetadata(data: DrawingMetadata | undefined);
    get worldScale(): Readonly<number>;
    set sheetViewId(id: string | undefined);
    /** Gets or sets if the measurement should be drawn. */
    get isVisible(): boolean;
    set isVisible(v: boolean);
    /** Gets or sets if the measurement is locked. Locked measurements have a different styling, cannot be edited, and cannot be cleared by the clear measurement tool. */
    get isLocked(): boolean;
    set isLocked(value: boolean);
    /** Gets or sets the group ID for the measurement. This is used to categorize the measurement in a meaningful way to the application. */
    get groupId(): string | undefined;
    set groupId(value: string | undefined);
    /** Gets or sets the subgroup ID for the measurement. This is used to categorize the measurement in a meaningful way to the application. */
    get subgroupId(): string | undefined;
    set subgroupId(value: string | undefined);
    /** Gets or sets the ID for the measurement. This is used to categorize the measurement in a meaningful way to the application. */
    get id(): string | undefined;
    set id(value: string | undefined);
    /** Gets or sets the display label for the measurement. */
    get label(): string | undefined;
    set label(value: string | undefined);
    /** Gets or sets the mame of the StyleSet to apply when drawing this measurement. If undefined, the default style is used. */
    get style(): string | undefined;
    set style(value: string | undefined);
    /** Gets or sets the name of the StyleSet to apply when drawing this measurement when it is locked. If undefined, the default lock style is used. */
    get lockStyle(): string | undefined;
    set lockStyle(value: string | undefined);
    /**
     * Computes the active style for the measurement.
     * @returns the active style based on the locking flag.  If the style is undefined, the default style is returned (default when unlocked, default-locked when locked).
     */
    get activeStyle(): string;
    /** Gets the views this measurement targets. */
    get viewTarget(): MeasurementViewTarget;
    get displayLabels(): boolean;
    set displayLabels(display: boolean);
    /** Communicates to the action toolbar this measurement wants to participate in actions. */
    get allowActions(): boolean;
    /** Protected constructor */
    protected constructor(props?: MeasurementProps);
    /** Copies the measurement data into a new instance.
     * @returns clone of this measurement.
     */
    clone<T extends Measurement>(): T;
    /**
     * Serializes the measurement's data into a JSON prop object. Subclasses participate by overriding the writeToJSON method.
     * @returns prop object containing the values of the measurement.
     */
    toJSON<T extends MeasurementProps>(): T;
    /**
     * Tests equality with another measurement.
     * @param other Measurement to test equality for.
     * @param opts Options for equality testing.
     * @returns true if the other measurement is equal, false if some property is not the same or if the measurement is not of the same type.
     */
    equals(other: Measurement, opts?: MeasurementEqualityOptions): boolean;
    /** Draw the measurement. This is called every frame, e.g. when the mouse moves. This is suitable for small or dynamic graphics, but if the measurement
     * has complicated graphics, consider using the decorateCached method.
     * @param context Decorate context for drawing to a viewport.
     */
    decorate(_context: DecorateContext): void;
    /** Draw any graphics that need to be cached. This is called when the scene changes, e.g. zoom or rotate.
      * @param context Decorate context for drawing to a viewport.
    */
    decorateCached(_context: DecorateContext): void;
    /** Test if the measurement was picked.
     * @param _pickContext Picking context to test against.
     * @returns true if the measurement has been picked, false otherwise.
     */
    testDecorationHit(_pickContext: MeasurementPickContext): boolean;
    /** Get a geometry stream representing the pickable geometry of the measurement. Usually this is simplier geometry than what is drawn.
     * @param _pickContext Picking context to test against.
     * @returns a geometry stream of pickable data or undefined.
     */
    getDecorationGeometry(_pickContext: MeasurementPickContext): GeometryStreamProps | undefined;
    /** Get a tooltip for this measurement.
     * @param _pickContext Picking context to test against.
     * @returns a tooltip HTML element or string.
     */
    getDecorationToolTip(_pickContext: MeasurementPickContext): Promise<HTMLElement | string>;
    /**
     * Register a handler to modify the behavior of the widget data shown.
     * @param handler Function that modifies the WidgetData
     * @param priority Priority of the handler, highest priority will execute last
     */
    static registerDataForMeasurementWidgetHandler(handler: MeasurementDataWidgetHandlerFunction, priority?: number): boolean;
    /**
     * Gets formatted property data for the measurement UI widget.
     * @returns promise with data or undefined if there is no data to display.
     */
    getDataForMeasurementWidget(): Promise<MeasurementWidgetData | undefined>;
    /**
     * Gets formatted property data for the measurement UI widget.
     * @returns promise with data or undefined if there is no data to display.
     */
    protected getDataForMeasurementWidgetInternal(): Promise<MeasurementWidgetData | undefined>;
    /**
     * Responds to a button event. By default this tests if the measurement was picked and opens the action toolbar.
     * @param pickContext Picking context to test against.
     * @returns Whether or not the event was handled.
     */
    onDecorationButtonEvent(pickContext: MeasurementPickContext): Promise<MeasurementButtonHandledEvent>;
    /** Cleans up any resources (e.g. IDisposable objects) */
    onCleanup(): void;
    /** Adjusts a point to account for Global Origin. This is required in order to display coordinates as text.
     * May return a reference to the original point, or a new point if the global origin is applied
     */
    protected adjustPointForGlobalOrigin(point: Point3d): Readonly<Point3d>;
    /** Adjusts point with the sheetToWorldTransform
     * This is used to display 3d world information in sheets
     */
    protected adjustPointWithSheetToWorldTransform(point: Point3d): Readonly<Point3d>;
    /**
     * Creates a new instance of the measurement subclass. This works well for most subclasses that have a parameterless constructor (or one that takes in an optional props object).
     * Otherwise, the subclass should override this if it has special needs to correctly instantiate a new instance of itself.
     */
    protected createNewInstance(): Measurement;
    /**
     * Copies data from the other measurement into this instance.
     * @param other Measurement to copy property values from.
     */
    protected copyFrom(other: Measurement): void;
    /**
     * Deserializes properties (if they exist) from the JSON object.
     * @param json JSON object to read data from.
     */
    protected readFromJSON(json: MeasurementProps): void;
    /**
     * Serializes properties to a JSON object.
     * @param json JSON object to append data to.
     */
    protected writeToJSON(json: MeasurementProps): void;
    /** Notify subclasses that style options have changed. This is to allow implementations to regenerate any cached graphics.
     * @param _isLock true if the lock style was changed, false if the regular style.
     * @param _prevStyle The previous style name.
     */
    protected onStyleChanged(_isLock: boolean, _prevStyle?: string): void;
    /** Notify subclasses the group ID changed.
     * @param _prevGroupid The previous group ID.
     */
    protected onGroupIdChanged(_prevGroupid?: string): void;
    /** Notify subclasses the subgroup ID changed.
     * @param _prevSubgroupId The previous subgroup ID.
     */
    protected onSubGroupIdChanged(_prevSubgroupId?: string): void;
    /** Notify subclasses the ID changed.
     * @param _prevId The previous ID.
     */
    protected onIdChanged(_prevId?: string): void;
    /**
     * Notify subclasses the label changed.
     * @param _prevLabel The previous label value.
     */
    protected onLabelChanged(_prevLabel?: string): void;
    /** Notify subclasses when the measurement's lock is toggled. */
    protected onLockToggled(): void;
    /** Notify subclasses when the display units have changed. */
    onDisplayUnitsChanged(): void;
    /** Notify subclasses when the transient ID has changed.
     * @param _prevId The previous ID, if any.
     */
    protected onTransientIdChanged(_prevId?: Id64String): void;
    /**
     * Notify subclasses when DrawingMetadata changes
     */
    protected onDrawingMetadataChanged(): void;
    /**
     * Notify subclasses when the display labels property has changed.
     */
    protected onDisplayLabelsToggled(): void;
    /** Parses a JSON object into a single or multiple measurements.
     * @param data JSON object
     * @returns single or multiple measurements or undefine if parsing failed, or the JSON object is undefined.
     */
    static parse(data?: any): Measurement | Measurement[] | undefined;
    /** Parses a JSON object into a single measurement. If the JSON object had multiple measurements, only the first
     * one is returned.
     * @param data JSON object
     * @returns single measurement or undefined if parsing failed.
     */
    static parseSingle(data?: any): Measurement | undefined;
    /** Serializes one or more measurements into one or more JSON objects. For each type of measurement, the result will be a JSON object with a single
     * named property representing the measuremnt (e.g. "distanceMeasurement") which itself will either be a single JSON object or an array if more than one. If all measurements
     * are the same type, a single JSON object is returned. If there are multiple measurement types (e.g. distance, area, etc) then an array is returned where each entry is a JSON
     * object with the single named property.
     * @param measurement one or more measurements.
     * @returns undefined if nothing could be serialized OR a single JSON object if all the measurements are of the same type OR an array of JSON objects.
     */
    static serialize(measurement: Measurement | Measurement[]): any | any[];
    /** Registers a measurement serializer that is used in the parse/serialize static methods. Once a serializer is registered, it cannot be dropped.
     * If you need to override a measurement, do so by subclassing the measurement and it's serializer.
     * @param serializer serializer that handles a unique measurement during parsing/serialization.
     * @throws error if the serializer's name is not unique.
     */
    static registerSerializer(serializer: MeasurementSerializer): MeasurementSerializer | undefined;
    /**
     * Finds a serializer for the given name.
     * @param measurementName measurement name that a serializer is associated with.
     * @returns the associated serializer or undefined if none exists for the given name.
     */
    static findSerializer(measurementName: string): MeasurementSerializer | undefined;
    /**
     * Invalidate decorations for all viewports that can draw the specified measurements.
     * @param measurements Array of measurements to invalidate views for.
     */
    static invalidateDecorationsForAll(measurements: Measurement[]): void;
}
//# sourceMappingURL=Measurement.d.ts.map