import type BaseGeometry from "./Geometry.js";
import type Point from "./Point.js";
import type { Curve as CurveJSON } from "../portal/jsonTypes.js";
import type { GeometryProperties as BaseGeometryProperties } from "./Geometry.js";

export interface PolylineProperties extends BaseGeometryProperties, Partial<Pick<Polyline, "curvePaths" | "paths">> {}

/**
 * A polyline contains an array of [paths](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#paths) and [spatialReference](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#spatialReference).
 * Each path is represented as an array of points. A polyline also has boolean-valued
 * [hasM](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasM) and [hasZ](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasZ) properties.
 *
 * @since 4.0
 * @see [Sample - Add graphics (MapView)](https://developers.arcgis.com/javascript/latest/sample-code/intro-graphics/)
 * @see [Sample - Add graphics (SceneView)](https://developers.arcgis.com/javascript/latest/sample-code/graphics-basic-3d/)
 */
export default class Polyline extends BaseGeometry {
  constructor(properties?: PolylineProperties);
  /**
   * An array consisting of points and [curve objects](https://developers.arcgis.com/rest/services-reference/enterprise/geometry-objects/#curve-objects) that define the polyline geometry.
   *
   * @example
   * // Polyline with two circular arc segments represented with curve objects.
   * const curvedLine = new Polyline({
   *   curvePaths: [
   *     [
   *       [-13950813.6947, 4028697.5532],
   *       [-13878602.7757, 4026346.5],
   *       {
   *         c: [
   *           [-13854084.6497, 4009553.2631],
   *           [-13841976.9737328, 4053525.320625]
   *         ]
   *       },
   *       {
   *         c: [
   *           [-13851733.5965, 4069673.0515],
   *           [-13791446.6027123, 4037209.59502735]
   *         ]
   *       }
   *     ]
   *   ],
   *   spatialReference: { wkid: 102100 }
   * });
   */
  accessor curvePaths: CurveJSON[][] | undefined;
  /**
   * An array of paths, or line segments, that make up the polyline. Each path is a two-dimensional
   * array of numbers representing the coordinates of each vertex in the path in the spatial reference of the view.
   * Each vertex is represented as an array of two, three, or four numbers.
   * The table below shows the various structures of a vertex array.
   * Case | Vertex array
   * --- | ---
   * [without z](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasZ) and [without m](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasM) | [x, y]
   * [without z](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasZ) and [with m](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasM) | [x, y, m]
   * [with z](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasZ) and [without m](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasM) | [x, y, z]
   * [with z](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasZ) and [with m](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html#hasM) | [x, y, z, m]
   *
   * @example
   * // 2D polyline with to paths with m-values (note that the 2nd path does not have m-values defined)
   * let paths = [
   *  [  // first path
   *   [-97.06138,32.837,5],
   *   [-97.06133,32.836,6],
   *   [-97.06124,32.834,7]
   *  ], [  // second path
   *   [-97.06326,32.759],
   *   [-97.06298,32.755]
   *  ]
   * ];
   *
   * let line = new Polyline({
   *   hasZ: false,
   *   hasM: true,
   *   paths: paths,
   *   spatialReference: { wkid: 4326 }
   * });
   */
  accessor paths: number[][][];
  /** The geometry type. */
  get type(): "polyline";
  /**
   * Adds a path, or line segment, to the polyline. When added, the index of the path is incremented by one.
   *
   * @param points - A polyline path. This can either be defined as an array of
   *                              Point geometries or an array of XY coordinates.
   * @returns Returns the polyline with the new path included.
   */
  addPath(points: number[][] | Point[]): this;
  /**
   * Creates a deep clone of Polyline object.
   *
   * @returns A new instance of a Polyline object equal to the object used to call `.clone()`.
   */
  clone(): Polyline;
  /**
   * Returns a point specified by a path and point in the path.
   *
   * @param pathIndex - The index of a path in the polyline.
   * @param pointIndex - The index of a point in a path.
   * @returns Returns the point along the Polyline located in the given path and point indices.
   */
  getPoint(pathIndex: number, pointIndex: number): Point | null | undefined;
  /**
   * Inserts a new point into a polyline.
   *
   * @param pathIndex - The index of the path in which to insert a point.
   * @param pointIndex - The index of the inserted point in the path.
   * @param point - The point to insert.
   * @returns Returns the updated polyline.
   */
  insertPoint(pathIndex: number, pointIndex: number, point: Point | number[]): this;
  /**
   * Removes a path from the Polyline. The index specifies which path to remove.
   *
   * @param index - The index of the path to remove from the polyline.
   * @returns Returns an array of points representing the removed path.
   */
  removePath(index: number): Point[] | null | undefined;
  /**
   * Removes a point from the polyline at the given `pointIndex` within the path identified by the given `pathIndex`.
   *
   * @param pathIndex - The index of the path containing the point to be removed.
   * @param pointIndex - The index of the point to be removed within the path.
   * @returns Returns the removed point.
   */
  removePoint(pathIndex: number, pointIndex: number): Point | null | undefined;
  /**
   * Updates a point in a polyline.
   *
   * @param pathIndex - The index of the path that contains the point to be updated.
   * @param pointIndex - The index of the point to be updated in the path.
   * @param point - Point geometry to update in the path.
   * @returns Returns the updated polyline.
   */
  setPoint(pathIndex: number, pointIndex: number, point: Point | number[]): this;
}