import type Accessor from "../../core/Accessor.js";
import type DrawAction from "./DrawAction.js";
import type { MapViewOrSceneView } from "../MapViewOrSceneView.js";
import type { DrawOptions } from "./types.js";

export interface DrawProperties extends Partial<Pick<Draw, "activeAction" | "view">> {}

export type ToolType = "point" | "polygon" | "polyline" | "multipoint" | "rectangle" | "circle" | "ellipse" | "triangle";

/**
 * The Draw class provides advanced drawing capabilities for developers who need complete control over
 * creating temporary graphics with different geometries. For example, if you want to prevent users from
 * drawing graphics with self-intersecting lines or overlapping polygons, then you can use this class to implement these rules.
 * The draw experience is built upon draw actions, which use the view events to
 * generate a set of coordinates for creating new geometries. Each geometry type has a corresponding draw action class.
 *
 * This class provides a simple interface for interacting with draw actions. After initializing a Draw instance,
 * you can call [create()](https://developers.arcgis.com/javascript/latest/references/core/views/draw/Draw/#create) to return a reference to the relevant
 * draw action. This draw action may then be used to create new geometries of the specified type.
 *
 * <span id="gestures"></span>
 * ## Pointer and keyboard gestures
 *
 * Pointer and keyboard gestures for drawing points, polylines, and polygons are described in the tables below.
 *
 * ### Drawing points
 *
 * Gesture | Action |
 * ---------|---------|
 * Left-click | Adds a point at the pointer location. |
 * Enter | Adds a point at the pointer location. |
 *
 * ### Drawing polylines and polygons
 *
 * Gesture | Action |
 * ---------|---------|
 * Left-click | Adds a vertex at the pointer location. |
 * Left-drag | Adds a vertex for each pointer move. |
 * Enter or Double-click | Completes the polyline or polygon. |
 * F | Adds a vertex to the polyline or polygon. |
 * Z | Incrementally undos actions recorded in the stack. |
 * R | Incrementally redos actions recorded in the stack. |
 *
 * To provide users with a simpler drawing experience, then use [SketchViewModel](https://developers.arcgis.com/javascript/latest/references/core/widgets/Sketch/SketchViewModel/) class.
 *
 * @since 4.5
 * @see [SketchViewModel](https://developers.arcgis.com/javascript/latest/references/core/widgets/Sketch/SketchViewModel/)
 * @see [Prevent drawing a self-intersecting line](https://developers.arcgis.com/javascript/latest/sample-code/draw-line/)
 * @see [Sketch widget](https://developers.arcgis.com/javascript/latest/sample-code/sketch-geometries/)
 * @example
 * // create a new instance of draw
 * let draw = new Draw({
 *   view: view
 * });
 *
 * // create an instance of draw polyline action
 * // the polyline vertices will be only added when
 * // the pointer is clicked on the view
 * let action = draw.create("polyline", {mode: "click"});
 *
 * // fires when a vertex is added
 * action.on("vertex-add", function (evt) {
 *   measureLine(evt.vertices);
 * });
 *
 * // fires when the pointer moves
 * action.on("cursor-update", function (evt) {
 *   measureLine(evt.vertices);
 * });
 *
 * // fires when the drawing is completed
 * action.on("draw-complete", function (evt) {
 *   measureLine(evt.vertices);
 * });
 *
 * // fires when a vertex is removed
 * action.on("vertex-remove", function (evt) {
 *   measureLine(evt.vertices);
 * });
 *
 * function measureLine(vertices) {
 *   view.graphics.removeAll();
 *
 *   let line = createLine(vertices);
 *   let lineLength = geometryEngine.geodesicLength(line, "miles");
 *   let graphic = createGraphic(line);
 *   view.graphics.add(graphic);
 * }
 *
 * function createLine(vertices) {
 *   let polyline = {
 *     type: "polyline", // autocasts as new Polyline()
 *     paths: vertices,
 *     spatialReference: view.spatialReference
 *   }
 *   return polyline;
 * }
 */
export default class Draw extends Accessor {
  /**
   * @example
   * // Typical usage
   * let draw = new Draw({
   *   view: view
   * });
   */
  constructor(properties?: DrawProperties);
  /**
   * A reference to the active [draw action](https://developers.arcgis.com/javascript/latest/references/core/views/draw/DrawAction/).
   * An instance of the draw action is created when [create()](https://developers.arcgis.com/javascript/latest/references/core/views/draw/Draw/#create) method is called.
   */
  accessor activeAction: DrawAction | null | undefined;
  /** The view in which geometries will be drawn by the user. */
  accessor view: MapViewOrSceneView;
  /**
   * Complete the current active drawing.
   *
   * @since 4.7
   */
  complete(): void;
  /**
   * Creates an instance of the requested draw action.
   *
   * @param drawAction - Name of the [draw action](https://developers.arcgis.com/javascript/latest/references/core/views/draw/DrawAction/) to create.
   * See the table below for a list of possible values and type of draw action it creates.
   *
   * **Possible Values**
   *
   * Geometry type | Draw action instance
   * ------------- | --------------------
   * point         | [PointDrawAction](https://developers.arcgis.com/javascript/latest/references/core/views/draw/PointDrawAction/)
   * multipoint    | [MultipointDrawAction](https://developers.arcgis.com/javascript/latest/references/core/views/draw/MultipointDrawAction/) (only supported in [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/))
   * polyline      | [PolylineDrawAction](https://developers.arcgis.com/javascript/latest/references/core/views/draw/PolylineDrawAction/)
   * polygon       | [PolygonDrawAction](https://developers.arcgis.com/javascript/latest/references/core/views/draw/PolygonDrawAction/)
   * rectangle, circle, ellipse | [SegmentDrawAction](https://developers.arcgis.com/javascript/latest/references/core/views/draw/SegmentDrawAction/)
   * @param drawOptions - Object of the drawing options for the geometry to be created.
   * @returns Returns an instance of the requested draw action.
   * @example let pointAction = draw.create("point");
   */
  create(drawAction: ToolType, drawOptions?: DrawOptions): DrawAction;
  /**
   * Resets the drawing by clearing the active action.
   *
   * @since 4.6
   */
  reset(): void;
}