import type Extent from "./Extent.js";
import type SpatialReference from "./SpatialReference.js";
import type { JSONSupport } from "../core/JSONSupport.js";
import type { SpatialReferenceProperties } from "./SpatialReference.js";

export interface GeometryProperties extends Partial<Pick<Geometry, "hasM" | "hasZ">> {
  /**
   * The spatial reference of the geometry.
   *
   * @default SpatialReference.WGS84 // wkid: 4326
   */
  spatialReference?: SpatialReferenceProperties;
}

/**
 * The base class for geometry objects.
 * This class has no constructor. To construct geometries see [Point](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/),
 * [Polyline](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polyline/), or [Polygon](https://developers.arcgis.com/javascript/latest/references/core/geometry/Polygon/).
 *
 * @since 4.0
 * @see [Graphic](https://developers.arcgis.com/javascript/latest/references/core/Graphic/)
 */
export default abstract class Geometry extends JSONSupport {
  /**
   * The cache is used to store values computed from geometries that need to be cleared or recomputed upon mutation.
   * An example is the extent of a polygon.
   */
  get cache(): Record<string, any>;
  /** The extent of the geometry. For a point, the extent is null. */
  get extent(): Extent | null | undefined;
  /**
   * Indicates if the geometry has M values.
   *
   * @default false
   */
  accessor hasM: boolean;
  /**
   * Indicates if the geometry has z-values (elevation).
   *
   * > [!WARNING]
   * >
   * > **Z-values** defined in a geographic or metric coordinate system are
   * > expressed in meters. However, in local scenes that use a
   * > projected coordinate system, vertical units are assumed to be the same as the
   * > horizontal units specified by the service.
   *
   * @default false
   */
  accessor hasZ: boolean;
  /**
   * The spatial reference of the geometry.
   *
   * @default SpatialReference.WGS84 // wkid: 4326
   */
  get spatialReference(): SpatialReference;
  set spatialReference(value: SpatialReferenceProperties);
  /** The geometry type. */
  get type(): "point" | "multipoint" | "polyline" | "polygon" | "extent" | "mesh";
  /**
   * Creates a deep clone of the geometry.
   *
   * @returns A new instance of a Geometry object equal to the object used to call `.clone()`.
   */
  clone(): Geometry;
}