import type Viewshed from "../../analysis/Viewshed.js";
import type ViewshedLayer from "../../layers/ViewshedLayer.js";
import type LayerView from "./LayerView.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { ViewshedPlacementResult } from "../3d/analysis/Viewshed/types.js";
import type { LayerViewProperties } from "./LayerView.js";

export interface ViewshedLayerViewProperties extends LayerViewProperties, Partial<Pick<ViewshedLayerView, "interactive" | "selectedViewshed">> {}

/**
 * Represents the [LayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/LayerView/) of a [ViewshedLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ViewshedLayer/)
 * after it has been added to a [Map](https://developers.arcgis.com/javascript/latest/references/core/Map/) in a [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
 *
 * The viewshed layer view controls whether the viewsheds in its associated
 * [ViewshedLayer.source](https://developers.arcgis.com/javascript/latest/references/core/layers/ViewshedLayer/#source) can be created or edited interactively.
 *
 * It allows to create new viewsheds interactively using the [place()](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#place) method,
 * or to make existing viewsheds selectable and editable by enabling the [interactive](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#interactive) property.
 * To select a viewshed, hover and click on any of its manipulators.
 *
 * The view for the layer can be retrieved using [SceneView.whenLayerView()](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#whenLayerView).
 *
 * ```js
 * // create new layer and add it to the map
 * const viewshedLayer = new ViewshedLayer();
 * view.map.add(viewshedLayer);
 *
 * // retrieve layer view for the layer
 * const layerView = await view.whenLayerView(viewshedLayer);
 * ```
 *
 * @since 4.31
 * @see [ViewshedLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ViewshedLayer/)
 * @see [Viewshed](https://developers.arcgis.com/javascript/latest/references/core/analysis/Viewshed/)
 * @see [ViewshedAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/ViewshedAnalysis/)
 * @see [ViewshedAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/ViewshedAnalysisView3D/)
 * @see [Sample - ViewshedLayer in slides](https://developers.arcgis.com/javascript/latest/sample-code/layers-viewshed/)
 * @see [Async cancellation with AbortController](https://developers.arcgis.com/javascript/latest/async-cancellation-with-abortcontroller/)
 */
export default abstract class ViewshedLayerView extends LayerView {
  /**
   * Enables interactivity for the [layer](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#layer). When set to `true` and the layer's
   * [ViewshedLayer.source](https://developers.arcgis.com/javascript/latest/references/core/layers/ViewshedLayer/#source) includes any
   * valid [ViewshedAnalysis.viewsheds](https://developers.arcgis.com/javascript/latest/references/core/analysis/ViewshedAnalysis/#viewsheds), they become selectable and editable.
   *
   * @default false
   */
  accessor interactive: boolean;
  /** The layer this layer view represents. */
  get layer(): ViewshedLayer;
  /**
   * The selected viewshed. If [interactive](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#interactive) is `true`, any viewshed in the
   * [layer](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#layer) can be selected by clicking on it in the view. As long as [interactive](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#interactive)
   * remains `true`, the properties of the selected viewshed can be edited by interacting with
   * manipulators in the view.
   */
  accessor selectedViewshed: Viewshed | null | undefined;
  /**
   * Starts the interactive creation of new viewsheds and adds them to the layer
   * [ViewshedLayer.source](https://developers.arcgis.com/javascript/latest/references/core/layers/ViewshedLayer/#source).
   *
   * The first click in the scene places the observer point and the second sets the viewshed's orientation.
   *
   * 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/references/core/views/layers/ViewshedLayerView/#place) method, but it allows to create multiple viewsheds in a row.
   *
   * Calling this method sets [interactive](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#interactive) to `true`.
   *
   * > [!WARNING]
   * >
   * > Note that when placing viewsheds interactively, the viewshed is created with a 1.5 meter vertical offset from the scene.
   * > _This behavior is subject to change in a future release._
   *
   * @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 viewshedLayerView.createViewsheds({ signal: abortController.signal });
   * } catch (error) {
   *   if (error.name === "AbortError") {
   *     console.log("Creation operation was cancelled.");
   *   }
   * }
   *
   * // cancel the placement operation at some later point
   * abortController.abort();
   */
  createViewsheds(options?: AbortOptions | null | undefined): Promise<void>;
  /**
   * Starts the interactive placement of a single viewshed, adding it to the [layer](https://developers.arcgis.com/javascript/latest/references/core/views/layers/ViewshedLayerView/#layer)'s
   * [ViewshedLayer.source](https://developers.arcgis.com/javascript/latest/references/core/layers/ViewshedLayer/#source).
   *
   * The first click in the scene places the observer point and the second sets the viewshed's orientation.
   *
   * 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/references/core/views/layers/ViewshedLayerView/#interactive) to `true`.
   *
   * > [!WARNING]
   * >
   * > Note that when placing viewsheds interactively, the viewshed is created with a 1.5 meter vertical offset from the scene.
   * > _This behavior is subject to change in a future release._
   *
   * @param options - An object specifying additional options.
   * @returns A promise which
   * resolves when the operation is completed successfully or rejected if it is canceled.
   * @since 4.33
   * @example
   * const abortController = new AbortController();
   *
   * try {
   *   await viewshedLayerView.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<ViewshedPlacementResult>;
}