/**
 * Transforms 2D geometry segment end points and interior points, thus preserving the geographic location of the segment interior and more accurately maintaining its original shape.
 * A maximum offset deviation parameter controls how much the result of the projection is allowed to deviate from the true preserved shape.
 *
 * Projecting your data between coordinate systems sometimes requires transforming
 * between geographic coordinate systems. Geographic transformations are used
 * to transform coordinates between spatial references that have different geographic
 * coordinate systems, and thus different datums.
 * Using the most suitable transformation ensures the best possible accuracy when
 * converting geometries from one spatial reference to another.
 *
 * The `geographicTransformationUtils` module provides the [getTransformation()](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-operators-support-geographicTransformationUtils.html#getTransformation) and
 * [getTransformations()](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-operators-support-geographicTransformationUtils.html#getTransformations) methods which return the default geographic transformation
 * for the given projection or a list of suitable geographic transformations.
 *
 * > [!WARNING]
 * >
 * > **Notes**
 * > Verify that `isLoaded()` returns `true` before using this module.
 * > Use `load()` to load this module's dependencies.
 *
 * @since 4.32
 * @see [projectOperator](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-operators-projectOperator.html)
 * @see [Spatial References](https://developers.arcgis.com/documentation/spatial-references/)
 * @see [Coordinate systems, map projections, and transformations](https://pro.arcgis.com/en/pro-app/latest/help/mapping/properties/coordinate-systems-and-projections.htm)
 * @see [Geographic datum transformations](https://pro.arcgis.com/en/pro-app/latest/help/mapping/properties/geographic-coordinate-system-transformation.htm)
 */
import type Extent from "../Extent.js";
import type SpatialReference from "../SpatialReference.js";
import type GeographicTransformation from "./support/GeographicTransformation.js";
import type { GeometryUnion, GeometryWithoutMeshUnion } from "../types.js";

export interface Options {
  /**
   * An extent used to help pick the correct transform.
   * This is not used if the `geographicTransformation` option is provided.
   * The extent's spatial reference should be the same as the `geometries` spatial reference.
   */
  areaOfInterestExtent?: Extent;
  /** The geographic transformation to use in the projections. */
  geographicTransformation?: GeographicTransformation;
  /**
   * Controls how much the result of the projection is allowed to deviate from the true preserved shape.
   * The default setting of 0 represents 100 * output tolerance.
   *
   * @default 0
   */
  maxDeviationInSrTo?: number;
  /**
   * A lower bound controlling the densification in the input coordinate system.
   * The default setting of 0 represents 1e-5 degrees. If the input coordinate system is a projected coordinate system, then this value is translated to length in linear units at the equator.
   *
   * @default 0
   */
  minSegmentLengthInDegrees?: number;
}

/**
 * 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-shapePreservingProjectOperator.html#isLoaded)
 */
export function load(): Promise<void>;

/**
 * Performs the shape preserving project operation on a single geometry.
 *
 * @param geometry - The geometry to be projected.
 * @param outSpatialReference - The spatial reference to which the input geometry is projected.
 * @param options - Additional options.
 * @returns The projected geometry or null.
 * @example
 * if (!shapePreservingProjectOperator.isLoaded()) {
 *   await shapePreservingProjectOperator.load();
 * }
 *
 * // Project a geometry to a different spatial reference while preserving its shape.
 * const geometry = shapePreservingProjectOperator.execute(polyline, spatialReference);
 */
export function execute(geometry: GeometryUnion, outSpatialReference: SpatialReference, options?: Options): GeometryWithoutMeshUnion | null | undefined;

/**
 * Performs the shape preserving project operation on multiple geometries.
 *
 * @param geometries - The geometries to be projected.
 * All the geometries must have the same spatial reference.
 * @param outSpatialReference - The spatial reference to which the input geometries are projected.
 * @param options - Additional options.
 * @returns Returns the projected geometries or null.
 */
export function executeMany(geometries: GeometryUnion[], outSpatialReference: SpatialReference, options?: Options): (GeometryWithoutMeshUnion | null | undefined)[];

/**
 * 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 `false`.
 */
export const supportsCurves: boolean | null | undefined;