/**
 * Finds closest vertices of a 2D geometry using geodesic distance.
 *
 * > [!WARNING]
 * >
 * > **Notes**
 * >
 * > Verify that `isLoaded()` returns `true` before using this module.
 * > Use `load()` to load this module's dependencies.
 *
 * ![Geodesic proximity operator](https://developers.arcgis.com/javascript/latest/assets/img/apiref/operators/geodesicProximity.png "Geodesic proximity operator")
 *
 * @since 4.31
 */
import type Point from "../Point.js";
import type { LengthUnit } from "../../core/units.js";
import type { GeometryUnion } from "../types.js";
import type { ProximityResult } from "./types.js";

export interface Options {
  /**
   * The length unit of the result distance.
   *
   * @default "meters"
   */
  unit?: LengthUnit;
}

export interface GetNearestCoordinateOptions extends Options {
  /**
   * When the parameter is set to true, this function will calculate the left/right side of a polyline or polygon.
   * Look for the result in the `isRightSide` property of the returned `ProximityResult` object.
   *
   * @default false
   */
  calculateLeftRightSide?: boolean;
  /**
   * The value controls the error of calculation.
   * The method uses shape preserving densification to approximate the input segments with great piecewise elliptical arcs.
   * When the value is zero or NaN, internally the operator uses 0.01 meters.
   * For other values, unless the `unit` option is set, the default is meters.
   *
   * @default NaN
   */
  maxDeviation?: number;
  /**
   * When `geometry` is a polygon, the function will test if `point` is inside of the polygon.
   * Points that are inside of the polygon have zero distance to the polygon.
   * When set to `false`, the function will not check if the point is inside of the polygon, but will only determine proximity to the boundary.
   *
   * @default true
   */
  testPolygonInterior?: boolean;
}

/**
 * Indicates if all dependencies of this module have been loaded.
 *
 * @returns Returns `true` if this module's dependencies have been loaded.
 */
export function isLoaded(): boolean;

/**
 * Loads this module's dependencies. This method must be called first if `isLoaded` returns `false`.
 *
 * @returns Resolves when the dependencies have been loaded.
 * @see [isLoaded()](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-operators-geodesicProximityOperator.html#isLoaded)
 */
export function load(): Promise<void>;

/**
 * Returns the nearest coordinate on the geometry to the given input point.
 * The operator interprets all segments in the shape preserving manner, that is it treats segments as if they are densified with a small step in the input spatial reference and then the calculation is performed geodesicly.
 *
 * @param geometry - The input geometry.
 * @param point - The point used to search for the nearest coordinate in `geometry`.
 * @param options - Additional options.
 * @returns Returns the result of proximity operation.
 * @example
 * if (!geodesicProximityOperator.isLoaded()) {
 *   await geodesicProximityOperator.load();
 * }
 *
 * // Calculate the nearest coordinate on a polyline to the given point
 * const result = geodesicProximityOperator.getNearestCoordinate(polyline, point);
 */
export function getNearestCoordinate(geometry: GeometryUnion, point: Point, options?: GetNearestCoordinateOptions): ProximityResult;

/**
 * Returns the nearest vertex on the geometry.
 *
 * @param geometry - The input geometry.
 * @param point - The point used to search for the nearest coordinate in the input `geometry`.
 * @param options - Additional options.
 * @returns Returns the result of proximity operation.
 * @example
 * if (!geodesicProximityOperator.isLoaded()) {
 *   await geodesicProximityOperator.load();
 * }
 *
 * // Calculate the nearest vertex on a polyline to the given point
 * const result = geodesicProximityOperator.getNearestVertex(polyline, point);
 */
export function getNearestVertex(geometry: GeometryUnion, point: Point, options?: Options): ProximityResult;

/**
 * Returns vertices of the geometry that are closer to the given point than the given radius.
 *
 * @param geometry - The input geometry.
 * @param point - The point used to search for the nearest coordinate in `geometry`.
 * @param searchRadius - The distance to search from the `point` to the nearest vertices in the `geometry`.
 * Unless the `unit` option is set, the default is meters.
 * @param maxVertexCountToReturn - The maximum number of vertices that will be returned. Must be a positive number.
 * @param options - Additional options.
 * @returns The array of vertices that are in the given search radius to the point.
 * The array is sorted by distance to the queryPoint with the closest point first.
 * When there are more than the `maxVertexCountToReturn` vertices to return, it returns the closest vertices.
 * The array will be empty when `geometry` is empty.
 * @example
 * if (!geodesicProximityOperator.isLoaded()) {
 *   await geodesicProximityOperator.load();
 * }
 *
 * // Calculate the nearest vertices on a polyline to the given point
 * const result = geodesicProximityOperator.getNearestVertices(polyline, point, 100, 5);
 */
export function getNearestVertices(geometry: GeometryUnion, point: Point, searchRadius: number, maxVertexCountToReturn: number, options?: Options): ProximityResult[];

/**
 * Indicates if the operator supports input geometries that contain curves.
 * The value is `null` or `undefined` until the operator is loaded, then it will always be `true`.
 */
export const supportsCurves: boolean | null | undefined;