import type Analysis from "./Analysis.js";
import type Polygon from "../geometry/Polygon.js";
import type { SystemOrAreaUnit } from "../core/units.js";
import type { PolygonProperties } from "../geometry/Polygon.js";
import type { AnalysisProperties } from "./Analysis.js";

export interface AreaMeasurementAnalysisProperties extends AnalysisProperties, Partial<Pick<AreaMeasurementAnalysis, "unit">> {
  /**
   * Polygon whose area is to be computed and displayed in the view.
   *
   * If the polygon has [z-values](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/#hasZ) then these will be treated
   * as absolute values.
   *
   * > [!WARNING]
   * >
   * > **Known Limitation**
   * >
   * > For polygons with multiple rings, only the measurement of the first [ring](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/#rings) will be displayed.
   */
  geometry?: PolygonProperties | null;
}

/**
 * AreaMeasurementAnalysis computes the area of a polygonal region and displays the measurement
 * in a [View](https://developers.arcgis.com/javascript/latest/references/core/views/View/).
 *
 * To display an area measurement of a [Polygon](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/), create
 * a new instance of AreaMeasurementAnalysis, add it to [SceneView.analyses](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#analyses)
 * or [MapView.analyses](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#analyses) and set the [geometry](https://developers.arcgis.com/javascript/latest/references/core/analysis/AreaMeasurementAnalysis/#geometry) property.
 *
 * Use the [AreaMeasurementAnalysisView2D](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/AreaMeasurementAnalysisView2D/) or [AreaMeasurementAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/AreaMeasurementAnalysisView3D/) to retrieve analysis results.
 *
 * ```js
 * // create analysis
 * const areaMeasurement = new AreaMeasurementAnalysis({
 *   geometry: new Polygon({ })
 * });
 *
 * // add to a view
 * view.analyses.add(areaMeasurement);
 *
 * // retrieve measured results from analysis view once available
 * const analysisView = await view.whenAnalysisView(areaMeasurement);
 * await reactiveUtils.whenOnce(() => analysisView.result);
 *
 * const result = analysisView.result;
 * ```
 *
 * To draw an area measurement interactively, use the
 * [AreaMeasurementAnalysisView2D.place()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/AreaMeasurementAnalysisView2D/#place) or
 * [AreaMeasurementAnalysisView3D.place()](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/AreaMeasurementAnalysisView3D/#place) method.
 *
 * ```js
 * const abortController = new AbortController();
 *
 * try {
 *   await analysisView.place({ signal: abortController.signal });
 * } catch (error) {
 *   if (error.name === "AbortError") {
 *     console.log("Placement operation was cancelled.");
 *   }
 * }
 *
 * // cancel the placement operation at some later point
 * abortController.abort();
 * ```
 *
 * How the area and perimeter are calculated depends on the view type, the spatial reference, and the measured perimeter.
 *
 * - In a [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) (2D):
 *   - For **geographic coordinate systems** (GCS) and **Web Mercator**, measurements are calculated geodetically
 *     (on the ellipsoid).
 *   - For **projected coordinate systems** (PCS), apart from Web Mercator, the area and perimeter are always calculated
 *     using Euclidean geometry within their respective PCS.
 *
 * - In a [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/) (3D):
 *   - For **geographic coordinate systems** (GCS) and **Web Mercator**, short measurements use a
 *     Euclidean computation in an [ECEF](https://en.wikipedia.org/wiki/ECEF) (Earth-Centered, Earth-Fixed) coordinate
 *     system (or an equivalent on other planets). Specifically, if the measurement's perimeter is ≤ 100 km the analysis
 *     uses Euclidean calculations. If the perimeter is > 100 km, it uses geodetic calculations.
 *   - For **projected coordinate systems** (PCS), apart from Web Mercator, the area and perimeter are always calculated
 *     in a Euclidean (in their respective PCS).
 *   - The area may be visualized and calculated in one of two ways:
 *     1. If the vertices are (approximately) coplanar, a measurement polygon is formed on that plane. The area
 *        and perimeter are then computed from the polygon geometry.
 *     2. If the vertices do not form a planar surface, the measurement polygon is projected to a horizontal plane
 *        and the area and perimeter are computed from the projected geometry.
 *
 * ![area-measurement-3d-types](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/area-measurement-3d-types.png)
 *
 * Use the [Area Measurement 3D component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-area-measurement-3d/) to display a user
 * interface for the area measurement analysis.
 *
 * @since 4.23
 * @see [AreaMeasurementAnalysisView2D](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/AreaMeasurementAnalysisView2D/)
 * @see [AreaMeasurementAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/AreaMeasurementAnalysisView3D/)
 * @see [Area Measurement 3D component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-area-measurement-3d/)
 * @see [Sample - Area measurement analysis object](https://developers.arcgis.com/javascript/latest/sample-code/analysis-area-measurement/)
 * @see [Sample - Analysis objects](https://developers.arcgis.com/javascript/latest/sample-code/analysis-objects/)
 */
export default class AreaMeasurementAnalysis extends Analysis {
  constructor(properties?: AreaMeasurementAnalysisProperties);
  /**
   * Polygon whose area is to be computed and displayed in the view.
   *
   * If the polygon has [z-values](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/#hasZ) then these will be treated
   * as absolute values.
   *
   * > [!WARNING]
   * >
   * > **Known Limitation**
   * >
   * > For polygons with multiple rings, only the measurement of the first [ring](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/#rings) will be displayed.
   */
  get geometry(): Polygon | null | undefined;
  set geometry(value: PolygonProperties | null | undefined);
  /** The type of analysis. For area measurement analysis, this is always "area-measurement". */
  get type(): "area-measurement";
  /** Unit system (imperial, metric) or specific unit used for displaying the computed area in the view. */
  accessor unit: SystemOrAreaUnit | null | undefined;
  /**
   * Indicates whether the analysis is ready to be computed and interacted with in the view. It requires the
   * geometry to be a valid polygon whose first ring contains at least 4 points, with the first and last points being
   * the same to close the polygon.
   *
   * @since 4.33
   */
  get valid(): boolean;
  /**
   * Clears the analysis by resetting the [geometry](https://developers.arcgis.com/javascript/latest/references/core/analysis/AreaMeasurementAnalysis/#geometry) property.
   *
   * @since 5.0
   */
  clear(): void;
}