/**
 * Geodesically buffer 2D geometries. A geodesic buffer creates an area around a geometry by calculating the shortest distance between points on the curved surface of the Earth, minimizing the distortion caused by map projections.
 * This results in a more accurate buffer when applied over larger geographic areas such as those covering multiple UTM zones, or when using global scales.
 *
 * > [!WARNING]
 * >
 * > **Notes**
 * >
 * > Verify that `isLoaded()` returns `true` before using this module.
 * > Use `load()` to load this module's dependencies.
 *
 * @since 4.31
 * @see [Sample - Geometry operator - geodesic buffers](https://developers.arcgis.com/javascript/latest/sample-code/gx-geodesicbuffer/)
 */
import type Polygon from "../Polygon.js";
import type { LengthUnit } from "../../core/units.js";
import type { GeometryUnion, GeodeticCurveType } from "../types.js";

export interface ExecuteOptions {
  /**
   * The type of geodetic curve used to determine the buffer.
   *
   * @default "geodesic"
   */
  curveType?: GeodeticCurveType;
  /**
   * The deviation offset to use for convergence.
   * Unless the `unit` option is set, the default is meters.
   * The geodesic arcs of the resulting buffer will be closer than the max deviation of the true buffer.
   * The default value of NaN will be a maximum of 0.01 meters and (up-to) 0.2% of the buffer distance.
   *
   * @default NaN
   */
  maxDeviation?: number;
  /**
   * The length unit of the buffer distances and max deviation.
   *
   * @default "meters"
   */
  unit?: LengthUnit;
}

export interface ExecuteManyOptions extends ExecuteOptions {
  /**
   * If true, the resulting buffer geometries will be unioned.
   *
   * @default false
   */
  union?: 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/references/core/geometry/operators/geodesicBufferOperator/#isLoaded)
 */
export function load(): Promise<void>;

/**
 * Creates a geodesic buffer around the input geometry.
 *
 * @param geometry - The geometry to buffer.
 * @param distance - The buffer distance for the geometry. Unless the `unit` option is set, the default is meters.
 * @param options - Additional options.
 * @returns Returns the buffered geometry or null.
 * @example
 * if (!geodesicBufferOperator.isLoaded()) {
 *   await geodesicBufferOperator.load();
 * }
 *
 * // Calculate the buffer of a polyline geometry
 * const bufferGeometry = geodesicBufferOperator.execute(polyline, 100);
 */
export function execute(geometry: GeometryUnion, distance: number, options?: ExecuteOptions): Polygon | null | undefined;

/**
 * Creates a geodesic buffer around the input geometries.
 *
 * @param geometries - The set of geometries to buffer.
 * All the geometries must have the same spatial reference.
 * @param distances - The buffer distance for each of the geometries. Unless the `unit` option is set, the default is meters.
 * If the size of the distances array is less than the number of geometries in the input geometries,
 * the last distance value is used for the rest of geometries.
 * @param options - Additional options.
 * @returns Returns the buffered geometries.
 */
export function executeMany(geometries: GeometryUnion[], distances: number[], options?: ExecuteManyOptions): Polygon[];

/**
 * 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`.
 * This will produce densified output geometries.
 */
export const supportsCurves: boolean | null | undefined;