import type Graphic from "../Graphic.js";
import type Analysis from "./Analysis.js";
import type ElevationProfileDisplayUnits from "./ElevationProfile/ElevationProfileDisplayUnits.js";
import type ElevationProfileViewOptions from "./ElevationProfile/ElevationProfileViewOptions.js";
import type Collection from "../core/Collection.js";
import type Polyline from "../geometry/Polyline.js";
import type ElevationInfo from "../symbols/support/ElevationInfo.js";
import type { AnalysisProperties } from "./Analysis.js";
import type { ElevationProfileDisplayUnitsProperties } from "./ElevationProfile/ElevationProfileDisplayUnits.js";
import type { ElevationProfileViewOptionsProperties } from "./ElevationProfile/ElevationProfileViewOptions.js";
import type { ElevationProfileLineUnion } from "./ElevationProfile/types.js";
import type { ElevationInfoProperties } from "../symbols/support/ElevationInfo.js";
import type { PolylineProperties } from "../geometry/Polyline.js";
import type { ElevationProfileLineSceneProperties } from "./ElevationProfile/ElevationProfileLineScene.js";
import type { ElevationProfileLineQueryProperties } from "./ElevationProfile/ElevationProfileLineQuery.js";
import type { ElevationProfileLineInputProperties } from "./ElevationProfile/ElevationProfileLineInput.js";
import type { ElevationProfileLineGroundProperties } from "./ElevationProfile/ElevationProfileLineGround.js";
import type { ReadonlyArrayOrCollection } from "../core/Collection.js";

export interface ElevationProfileAnalysisProperties extends AnalysisProperties {
  /**
   * Unit systems (imperial, metric) or specific units used for computing and displaying elevation profile results.
   *
   * If not specified, units are chosen automatically based on the magnitude of the results. The effective units can be accessed
   * through the [ElevationProfileAnalysisView2D.results](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/ElevationProfileAnalysisView2D/#results)
   * or [ElevationProfileAnalysisView3D.results](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/ElevationProfileAnalysisView3D/#results) properties.
   */
  displayUnits?: ElevationProfileDisplayUnitsProperties;
  /**
   * Specifies how the [geometry's](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfileAnalysis/#geometry) Z values are interpreted, for example to compute elevations for an
   * [input](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfile/ElevationProfileLineInput/) profile line. This property can only
   * be used in a [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
   */
  elevationInfo?: ElevationInfoProperties | null;
  /** The [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/) along which elevation is to be sampled. */
  geometry?: PolylineProperties | null;
  /**
   * The collection of profile lines to compute and display. Each profile line defines a different source for sampling
   * elevation along the input geometry (such as ground, input geometry itself, custom elevation sources, or scene
   * content), and includes settings for how the resulting line will appear in charts and in the view.
   *
   * In a [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/), [ElevationProfileLineScene](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfile/ElevationProfileLineScene/) is
   * not supported.
   */
  profiles?: ReadonlyArrayOrCollection<((ElevationProfileLineGroundProperties & { type: "ground" }) | (ElevationProfileLineInputProperties & { type: "input" }) | (ElevationProfileLineQueryProperties & { type: "query" }) | (ElevationProfileLineSceneProperties & { type: "scene" }))> | null;
  /** Configuration options for visualizing an elevation profile within a view. */
  viewOptions?: ElevationProfileViewOptionsProperties;
}

/**
 * The `ElevationProfileAnalysis` class enables programmatic creation and management of elevation profiles in both,
 * a [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/) and a [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/). An elevation profile visualizes elevation
 * changes along a specified [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/), which is provided via the [geometry](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfileAnalysis/#geometry) property.
 *
 * This analysis supports multiple profile lines, each representing a different source or method for sampling elevation,
 * such as ground, input geometry, custom elevation sources, or scene content. The configuration of these lines is managed
 * through the [profiles](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfileAnalysis/#profiles) property.
 *
 * To add an elevation profile analysis to a view:
 *
 * ```js
 * const elevationProfileAnalysis = new ElevationProfileAnalysis({
 *   profiles: [
 *     // Profile line that samples the ground elevation
 *     {
 *       type: "ground",
 *       color: "rgb(150, 75, 0)",
 *     }
 *   ],
 *   geometry: new Polyline({ })
 * });
 *
 * view.analyses.add(elevationProfileAnalysis);
 * ```
 *
 * The [MapView.analyses](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#analyses) and
 * [SceneView.analyses](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#analyses) collections can contain multiple elevation profile
 * analyses simultaneously.
 *
 * Use the [ElevationProfileAnalysisView2D](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/ElevationProfileAnalysisView2D/) or
 * [ElevationProfileAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/ElevationProfileAnalysisView3D/) to retrieve the analysis results.
 * The combined statistics, as well as results for each computed profile line, can be then visualized in a custom chart using any charting library,
 * embedded in a dashboard, exported as a CSV file, or used for further calculations.
 *
 * ```js
 * // Get the analysis view
 * const analysisView = await view.whenAnalysisView(elevationProfileAnalysis);
 * // Retrieve the results, once they are ready
 * reactiveUtils.watch(
 *   () => analysisView.progress,
 *   (progress) => {
 *     if (progress === 1) {
 *       console.log("Results are computed", analysisView.results);
 *       console.log("Statistics are computed", analysisView.statistics);
 *     }
 *   }
 * );
 * ```
 *
 * To interactively place an elevation profile, use the
 * [ElevationProfileAnalysisView2D.place()](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/ElevationProfileAnalysisView2D/#place) or
 * [ElevationProfileAnalysisView3D.place()](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/ElevationProfileAnalysisView3D/#place) methods.
 *
 * ```js
 * const abortController = new AbortController();
 *
 * try {
 *   // Start placing a new profile line interactively
 *   await analysisView.place({ signal: abortController.signal });
 * } catch (error) {
 *   if (error.name === "AbortError") {
 *     console.log("Placement operation was cancelled.");
 *   }
 * }
 *
 * // Cancel the operation at some later point
 * abortController.abort();
 * ```
 *
 * How distances are computed depends on the scene's or map's spatial reference:
 *
 * * In geographic coordinate systems (GCS) and in Web Mercator, distances are computed geodetically, taking the
 * curvature of the planet into consideration.
 * * In projected coordinate systems (PCS), apart from Web Mercator, the distances are computed in a Euclidean manner (in their respective PCS).
 *
 * For a ready-to-use UI, use the [Elevation Profile component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-elevation-profile/),
 * which allows users to interactively place an elevation profile and view the results in a chart.
 *
 * @since 4.34
 * @see [ElevationProfileAnalysisView2D](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/ElevationProfileAnalysisView2D/)
 * @see [ElevationProfileAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/ElevationProfileAnalysisView3D/)
 * @see [Sample - Elevation Profile analysis](https://developers.arcgis.com/javascript/latest/sample-code/analysis-elevation-profile/)
 * @see [Sample - Analysis objects](https://developers.arcgis.com/javascript/latest/sample-code/analysis-objects/)
 * @see [Elevation Profile component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-elevation-profile/)
 * @see [Async cancellation with AbortController](https://developers.arcgis.com/javascript/latest/async-cancellation-with-abortcontroller/)
 */
export default class ElevationProfileAnalysis extends Analysis {
  constructor(properties?: ElevationProfileAnalysisProperties);
  /**
   * Unit systems (imperial, metric) or specific units used for computing and displaying elevation profile results.
   *
   * If not specified, units are chosen automatically based on the magnitude of the results. The effective units can be accessed
   * through the [ElevationProfileAnalysisView2D.results](https://developers.arcgis.com/javascript/latest/references/core/views/2d/analysis/ElevationProfileAnalysisView2D/#results)
   * or [ElevationProfileAnalysisView3D.results](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/ElevationProfileAnalysisView3D/#results) properties.
   */
  get displayUnits(): ElevationProfileDisplayUnits;
  set displayUnits(value: ElevationProfileDisplayUnitsProperties);
  /**
   * Specifies how the [geometry's](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfileAnalysis/#geometry) Z values are interpreted, for example to compute elevations for an
   * [input](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfile/ElevationProfileLineInput/) profile line. This property can only
   * be used in a [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
   */
  get elevationInfo(): ElevationInfo | null | undefined;
  set elevationInfo(value: ElevationInfoProperties | null | undefined);
  /** The [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/) along which elevation is to be sampled. */
  get geometry(): Polyline | null | undefined;
  set geometry(value: PolylineProperties | null | undefined);
  /**
   * The collection of profile lines to compute and display. Each profile line defines a different source for sampling
   * elevation along the input geometry (such as ground, input geometry itself, custom elevation sources, or scene
   * content), and includes settings for how the resulting line will appear in charts and in the view.
   *
   * In a [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/), [ElevationProfileLineScene](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfile/ElevationProfileLineScene/) is
   * not supported.
   */
  get profiles(): Collection<ElevationProfileLineUnion>;
  set profiles(value: ReadonlyArrayOrCollection<((ElevationProfileLineGroundProperties & { type: "ground" }) | (ElevationProfileLineInputProperties & { type: "input" }) | (ElevationProfileLineQueryProperties & { type: "query" }) | (ElevationProfileLineSceneProperties & { type: "scene" }))> | null | undefined);
  /** The analysis type. */
  get type(): "elevation-profile";
  /**
   * Indicates whether the analysis is ready to be computed and interacted with in the view. It requires the geometry
   * to be a valid [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/) with at least one path containing two points.
   */
  get valid(): boolean;
  /** Configuration options for visualizing an elevation profile within a view. */
  get viewOptions(): ElevationProfileViewOptions;
  set viewOptions(value: ElevationProfileViewOptionsProperties);
  /**
   * Clears the analysis by resetting the [geometry](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfileAnalysis/#geometry) and
   * [elevationInfo](https://developers.arcgis.com/javascript/latest/references/core/analysis/ElevationProfileAnalysis/#elevationInfo) properties.
   *
   * @since 5.0
   */
  clear(): void;
  /**
   * Sets the analysis geometry and elevation info from the provided feature.
   *
   * @param feature - The feature from which to set the analysis geometry and elevation info.
   * @since 5.0
   */
  setGeometryFromFeature(feature: Graphic): void;
}