import { Point, Vector3 } from '@vertexvis/geometry';
import { Disposable, Listener } from '@vertexvis/utils';
import { RaycasterLike } from '../../lib/scenes';
import { PointToPointHitTester } from './hitTest';
import { Anchor } from './utils';
/**
 * A measurement result that represents the distance between two points.
 */
export interface PointToPointMeasurementResult {
    /**
     * The distance, in world units, between two points. This value is only
     * populated if the result is valid.
     */
    distance?: number;
    /**
     * The first point, in world units.
     */
    start: Vector3.Vector3;
    /**
     * The second point, in world units.
     */
    end: Vector3.Vector3;
    /**
     * Indicates if this result is valid. A value of `false` indicates that one of
     * the points does not touch any geometry.
     */
    valid: boolean;
}
/**
 * Provides APIs to perform local or remote hit tests.
 */
export interface PointToPointHitProvider {
    /**
     * Returns a hit tester that can be used to test if a point is over geometry
     * without having to do an API call.
     */
    hitTester(): PointToPointHitTester;
    /**
     * Returns a raycaster that can be used to perform hits through API calls.
     */
    raycaster(): Promise<RaycasterLike>;
}
/**
 * A controller to handle point-to-point measurement interactions.
 */
export declare class PointToPointInteractionController {
    private readonly model;
    constructor(model: PointToPointInteractionModel);
    /**
     * Returns an interaction handler to perform a new measurement.
     *
     * @param pt A point in viewport coordinates.
     * @param hits A provider to perform hits.
     * @returns An interaction handler, or `undefined` if the point does not hit
     *  any geometry.
     */
    newMeasurement(pt: Point.Point, hits: PointToPointHitProvider): PointToPointInteraction | undefined;
    /**
     * Returns an interaction handler to edit an existing measurement.
     *
     * @param anchor The anchor to edit.
     * @returns An interaction handler to edit a measurement.
     */
    editMeasurement(anchor: Anchor): PointToPointInteraction;
    /**
     * Clears the position of the feedback indicator.
     */
    clearIndicator(): void;
    /**
     * Updates the position of the feedback indicator.
     *
     * @param pt A point, in viewport coordinates.
     * @param hits A provider to perform hits.
     * @returns `true` if the indicator is over geometry.
     */
    moveIndicator(pt: Point.Point, hits: PointToPointHitProvider): boolean;
}
/**
 * The model for point-to-point interactions.
 */
export declare class PointToPointInteractionModel {
    private indicator?;
    private measurement?;
    private measurementChanged;
    private indicatorChanged;
    /**
     * Returns a model that doesn't have the indicator or measurement set.
     */
    static empty(): PointToPointInteractionModel;
    /**
     * Returns the current measurement for the interaction.
     */
    getMeasurement(): PointToPointMeasurementResult | undefined;
    /**
     * Updates the measurement and emits a change event.
     *
     * @param measurement The new measurement.
     */
    setMeasurement(measurement: PointToPointMeasurementResult | undefined): void;
    /**
     * Updates the measurement from the given values. If `start` or `end` are
     * `undefined` the measurement will be cleared.
     *
     * @param start The start point.
     * @param end The end point.
     * @param valid `true` if the measurement is valid.
     */
    setMeasurementFromValues(start: Vector3.Vector3 | undefined, end: Vector3.Vector3 | undefined, valid: boolean): void;
    /**
     * Adds a callback that is invoked when the measurement changes.
     *
     * @param listener The callback to register.
     * @returns A `Disposable` to remove the event listener.
     */
    onMeasurementChanged(listener: Listener<PointToPointMeasurementResult | undefined>): Disposable;
    /**
     * Gets the position representing the feedback indicator.
     */
    getIndicator(): Vector3.Vector3 | undefined;
    /**
     * Updates the position of the feedback indicator.
     */
    setIndicator(pt: Vector3.Vector3 | undefined): void;
    /**
     * Adds a callback that is invoked when the feedback indicator position
     * changes.
     *
     * @param listener The callback to register.
     * @returns A `Disposable` to remove the event listener.
     */
    onIndicatorChanged(listener: Listener<Vector3.Vector3 | undefined>): Disposable;
}
/**
 * An interface for performing point-to-point measurement interactions.
 *
 * @see {@link PointToPointInteractionController} to start an interaction.
 */
export interface PointToPointInteraction {
    /**
     * UI should call this for each user iteration.
     *
     * @param pt A point, in viewport coordinates.
     * @param hits A provider to perform hits.
     */
    update(pt: Point.Point, hits: PointToPointHitProvider): void;
    /**
     * UI should call this when the user interaction is finished. Returns a
     * `Promise` that resolves with the final measurement.
     *
     * @param pt A point, in viewport coordinates.
     * @param hits A provider to perform hits.
     */
    finish(pt: Point.Point, hits: PointToPointHitProvider): Promise<PointToPointMeasurementResult>;
}
