import type DimensionAnalysis from "../../../analysis/DimensionAnalysis.js";
import type LengthDimension from "../../../analysis/LengthDimension.js";
import type AnalysisView3D from "./AnalysisView3D.js";
import type LengthDimensionResult from "../../analysis/LengthDimensionResult.js";
import type { ReadonlyCollection } from "../../../core/Collection.js";
import type { AbortOptions } from "../../../core/promiseUtils.js";
import type { DimensionPlacementResult } from "./Dimension/types.js";

export interface DimensionAnalysisView3DProperties extends Partial<Pick<DimensionAnalysisView3D, "interactive" | "selectedDimension" | "visible">> {
  /** The dimension analysis object associated with the analysis view. */
  analysis?: DimensionAnalysis;
}

/**
 * Represents the analysis view of a [DimensionAnalysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-DimensionAnalysis.html)
 * after it has been added to [SceneView.analyses](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#analyses).
 *
 * The DimensionAnalysisView3D is responsible for rendering a [DimensionAnalysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-DimensionAnalysis.html)
 * using custom visualizations.
 *
 * It allows to create new dimensions interactively using the [place()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#place) method, query measured [results](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#results),
 * or to make existing dimensions selectable and editable by enabling the [interactive](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#interactive) property.
 * To select a dimension, hover and click on its offset manipulator.
 *
 * The view for an analysis can be retrieved using [SceneView.whenAnalysisView()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#whenAnalysisView)
 * similar to how layer views are retrieved for layers using [SceneView.whenLayerView()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#whenLayerView).
 *
 * ```js
 * // create new analysis and add it to the view
 * const dimensionAnalysis = new DimensionAnalysis();
 * view.analyses.add(dimensionAnalysis);
 *
 * // retrieve analysis view for the analysis
 * const dimensionAnalysisView = await view.whenAnalysisView(dimensionAnalysis);
 * ```
 *
 * > [!WARNING]
 * >
 * > **Things to consider:**
 * > Snapping is enabled by default. This can be temporarily disabled by holding the `CTRL` key.
 * > Layer types currently supported for snapping are: [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html), [GraphicsLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GraphicsLayer.html) (except Mesh geometries),
 * > [GeoJSONLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GeoJSONLayer.html), [WFSLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-WFSLayer.html), [CSVLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-CSVLayer.html),
 * > [3D Object SceneLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-SceneLayer.html), and [BuildingSceneLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-BuildingSceneLayer.html).
 *
 * @since 4.33
 * @see [DimensionAnalysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-DimensionAnalysis.html)
 * @see [LengthDimension](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-LengthDimension.html)
 * @see [DimensionSimpleStyle](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-DimensionSimpleStyle.html)
 * @see [DimensionLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-DimensionLayer.html)
 * @see [DimensionLayerView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-DimensionLayerView.html)
 * @see [Sample - Length dimensioning](https://developers.arcgis.com/javascript/latest/sample-code/layers-dimension/)
 * @see [Sample - Analysis objects](https://developers.arcgis.com/javascript/latest/sample-code/analysis-objects/)
 */
export default class DimensionAnalysisView3D extends AnalysisView3D {
  constructor(properties?: DimensionAnalysisView3DProperties);
  /** The dimension analysis object associated with the analysis view. */
  get analysis(): DimensionAnalysis;
  /**
   * Enables interactivity for the [analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#analysis). When set to `true` and the analysis includes any
   * valid [DimensionAnalysis.dimensions](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-DimensionAnalysis.html#dimensions), they become selectable and editable.
   *
   * @default false
   */
  accessor interactive: boolean;
  /**
   * Results for each dimension in the [analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#analysis).
   *
   * The order of results matches the order of [DimensionAnalysis.dimensions](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-DimensionAnalysis.html#dimensions),
   * so if the index of the dimension is known the collection can be indexed directly:
   *
   * ```js
   * const dimensionAnalysisView = await view.whenAnalysisView(dimensionAnalysis);
   * const result = dimensionAnalysisView.results.at(dimensionIdx);
   * ```
   *
   * Given a [dimension](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-LengthDimension.html) object, the results collection can also be searched:
   *
   * ```js
   * const result = dimensionAnalysisView.results.find((result) => result.dimension === dimensionObject);
   * ```
   */
  get results(): ReadonlyCollection<LengthDimensionResult>;
  /**
   * The selected dimension. If [interactive](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#interactive) is `true`, any dimension in the
   * [analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#analysis) can be selected by clicking on it in the view. As long as [interactive](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#interactive)
   * remains `true`, the properties of the selected dimension can be edited by interacting with
   * manipulators in the view.
   */
  accessor selectedDimension: LengthDimension | null | undefined;
  /** The analysis view type. */
  get type(): "dimension-view-3d";
  /** When `true`, the [analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#analysis) is visualized in the view. */
  accessor visible: boolean;
  /**
   * Starts the interactive creation of new dimensions and adds them to the [analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#analysis).
   *
   * The first click places start point and the second sets end point.
   *
   * The creation process will finish when the user double-clicks the mouse or presses the escape key.
   * To stop the creation programmatically, pass an abort signal as an argument when calling the method.
   *
   * This method is similar to the [place()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#place) method, but it allows to create multiple dimensions in a row.
   *
   * Calling this method sets [interactive](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#interactive) to `true`.
   *
   * @param options - An object specifying additional options.
   * @returns A promise which resolves when creation is completed successfully or rejected if it is
   * canceled.
   * @example
   * const abortController = new AbortController();
   *
   * try {
   *   await analysisView.createLengthDimensions({ 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();
   */
  createLengthDimensions(options?: AbortOptions | null | undefined): Promise<void>;
  /**
   * Starts the interactive placement of a single dimension, adding it to the [analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#analysis).
   *
   * The first click places start point and the second sets end point.
   *
   * The placement operation will finish when the user presses the escape key.
   * To stop the placing programmatically, pass an abort signal as an argument when calling the method.
   *
   * Calling this method sets [interactive](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-analysis-DimensionAnalysisView3D.html#interactive) to `true`.
   *
   * @param options - An object specifying additional options.
   * @returns A promise which
   * resolves when the operation is completed successfully or rejected if it is canceled.
   * @example
   * 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();
   */
  place(options?: AbortOptions | null | undefined): Promise<DimensionPlacementResult>;
}