/// <reference path="../../index.d.ts" />
import type SceneView from "@arcgis/core/views/SceneView.js";
import type DirectLineMeasurementAnalysis from "@arcgis/core/analysis/DirectLineMeasurementAnalysis.js";
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ArcgisReferenceElement } from "../types.js";
import type { DirectLineMeasurement3DState } from "./types.js";
import type { T9nMeta } from "@arcgis/lumina/controllers";
import type { Icon as Icon } from "@esri/calcite-components/components/calcite-icon";
import type { SystemOrLengthUnit } from "@arcgis/core/core/units.js";

/**
 * The Direct Line Measurement 3D component can be added to an [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/)
 * component to calculate and display vertical, horizontal, and direct distances between two points.
 *
 * [![measurement-line-3d](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/3D_DirectLineMeasurement_widget.avif)](https://developers.arcgis.com/javascript/latest/sample-code/measurement-3d/)
 *
 * How distances are computed depends on the scene's spatial reference.
 *
 * In **geographic coordinate systems** (GCS) and in **Web Mercator**:
 * - Direct distance is computed in a Euclidean manner, in an [ECEF](https://en.wikipedia.org/wiki/ECEF) coordinate system (or equivalent on other planets);
 * - Horizontal distance is computed geodetically, taking into consideration the curvature of the planet;
 * - Vertical distance is computed as an elevation difference.
 *
 * In **projected coordinate systems** (PCS), apart from Web Mercator, all three distances (direct, horizontal, and vertical)
 *  are computed in a Euclidean manner (in their respective PCS).
 *
 * Direct Line Measurement 3D component visualizes and labels the direct, horizontal, and vertical distances and displays the same values
 * in the UI panel. When the distance between the points is greater than 100 kilometers,
 * the measurement visualization is simplified, and only the horizontal and vertical distances are calculated.
 * The direct distance option becomes unavailable.
 *
 * ![measurement-line-3d](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/direct-line-measurement-3d.avif)
 *
 * When the component is active, a horizontal "laser" line is drawn which indicates the height at the current mouse position.
 * This line can help in analyzing the heights of objects relative to each other and the terrain.
 * A second laser line shows the intersection of the scene with the vertical plane that passes through the checkered line.
 *
 * **Things to consider**
 *
 * * Direct Line Measurement 3D is designed to work in the Scene component. For measurements in the [arcgis-map](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-map/)
 * component, use [arcgis-distance-measurement-2d](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-distance-measurement-2d/).
 * * 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/references/core/layers/FeatureLayer/),
 * [GraphicsLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/GraphicsLayer/) (except Mesh geometries),
 * [GeoJSONLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/GeoJSONLayer/),
 * [WFSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WFSLayer/),
 * [CSVLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/CSVLayer/),
 * [3D Object SceneLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/SceneLayer/),
 * and [BuildingSceneLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/BuildingSceneLayer/).
 *
 * **See also**
 *
 * - [DirectLineMeasurementAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/DirectLineMeasurementAnalysis/)
 * - [Sample - Measurement in 3D](https://developers.arcgis.com/javascript/latest/sample-code/measurement-3d/)
 * - [Sample - Analysis objects](https://developers.arcgis.com/javascript/latest/sample-code/analysis-objects/)
 * - [Sample - Color theming for interactive tools](https://developers.arcgis.com/javascript/latest/sample-code/view-theme/)
 *
 * @since 4.33
 */
export abstract class ArcgisDirectLineMeasurement3d extends LitElement {
  /**
   * The [DirectLineMeasurementAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/DirectLineMeasurementAnalysis/)
   * created or modified by the component.
   *
   * When connecting the Direct Line Measurement 3D component to an [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/)
   * component, it automatically creates an empty analysis and adds it to the Scene's
   * [arcgis-scene.analyses](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/#analyses) collection.
   * You can then wait for the [DirectLineMeasurementAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/DirectLineMeasurementAnalysisView3D/)
   * to be created before accessing the analysis results.
   *
   * ```js
   * // Get the Scene component and the Direct Line Measurement 3D component, and wait until both are ready.
   * const viewElement = document.querySelector("arcgis-scene");
   * await viewElement.viewOnReady();
   * const directLineMeasurement3dElement = document.querySelector("arcgis-direct-line-measurement-3d");
   * await directLineMeasurement3dElement.componentOnReady();
   *
   * // Get the DirectLineMeasurementAnalysis created by the Direct Line Measurement 3D component.
   * const analysis = directLineMeasurement3dElement.analysis;
   *
   * // Get the DirectLineMeasurementAnalysisView3D and watch for results.
   * const analysisView = await viewElement.whenAnalysisView(analysis);
   * const handle = reactiveUtils.watch(
   *   () => analysisView?.result,
   *   () => {
   *     console.log("Analysis results:", analysisView.result);
   *   },
   * );
   * ```
   * Whenever the component is destroyed, the analysis is automatically removed from the collection.
   *
   * Alternatively, a programmatically created [DirectLineMeasurementAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/DirectLineMeasurementAnalysis/)
   * can be provided to the component.
   * Then, the application itself needs to add it to and later remove it from the analyses collection of the Scene component.
   *
   * ```js
   * // Create the DirectLineMeasurementAnalysis.
   * const directLineAnalysis = new DirectLineMeasurementAnalysis({
   *    startPoint: new Point({
   *      spatialReference: { latestWkid: 3857, wkid: 102100 },
   *      x: -13624995.61798748,
   *      y: 4550334.030096778,
   *      z: 63.378210234455764
   *    }),
   *    endPoint: new Point({
   *      spatialReference: { latestWkid: 3857, wkid: 102100 },
   *      x: -13624921.53589075,
   *      y: 4550407.42357004,
   *      z: 63.3783810287714
   *    }),
   * });
   * // Get the Scene component and the Direct Line Measurement 3D component, and wait until both are ready.
   * const viewElement = document.querySelector("arcgis-scene");
   * await viewElement.viewOnReady();
   * const directLineMeasurement3dElement = document.querySelector("arcgis-direct-line-measurement-3d");
   * await directLineMeasurement3dElement.componentOnReady();
   *
   * // Add the analysis to the analyses collection of the Scene component.
   * viewElement.analyses.add(directLineAnalysis);
   *
   * // Connect the analysis to the measurement component:
   * directLineMeasurement3dElement.analysis = directLineAnalysis;
   * ```
   */
  accessor analysis: DirectLineMeasurementAnalysis;
  /**
   * If true, the component will not be destroyed automatically when it is
   * disconnected from the document. This is useful when you want to move the
   * component to a different place on the page, or temporarily hide it. If this
   * is set, make sure to call the [destroy()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-direct-line-measurement-3d/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * If true, the button that starts a new measurement will be hidden.
   *
   * @default false
   * @since 5.0
   */
  accessor hideStartButton: boolean;
  /**
   * If true, the unit selection dropdown will be hidden.
   *
   * @default false
   * @since 5.0
   */
  accessor hideUnitSelect: boolean;
  /**
   * Indicates whether the component's visualization is hidden in the view.
   *
   * @default false
   * @since 5.0
   */
  accessor hideVisualization: boolean;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @default "measure-line"
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  accessor icon: Icon["icon"] | undefined;
  /** The component's default label. */
  accessor label: string | undefined;
  /** @internal */
  protected messages: {
      componentLabel: string;
      direct: string;
      distance: string;
      hint: string;
      horizontal: string;
      newMeasurement: string;
      snappingDisablePrompt: string;
      snappingDisablePromptAlternate: string;
      unit: string;
      unsupported: string;
      vertical: string;
  } & T9nMeta<{
      componentLabel: string;
      direct: string;
      distance: string;
      hint: string;
      horizontal: string;
      newMeasurement: string;
      snappingDisablePrompt: string;
      snappingDisablePromptAlternate: string;
      unit: string;
      unsupported: string;
      vertical: string;
  }>;
  /**
   * By assigning the `id` attribute of the Map or Scene component to this property, you can position a child component anywhere in the DOM while still maintaining a connection to the Map or Scene.
   *
   * @see [Associate components with a Map or Scene component](https://developers.arcgis.com/javascript/latest/programming-patterns/#associate-components-with-a-map-or-scene-component)
   */
  accessor referenceElement: ArcgisReferenceElement | string | undefined;
  /**
   * The component's state. The values mean the following:
   *
   * * `disabled` -  not ready yet
   * * `ready` - ready for measuring
   * * `measuring` - currently measuring
   * * `measured` - measuring has finished
   */
  get state(): DirectLineMeasurement3DState;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the distance values. Possible values are listed in
   * [unitOptions](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-direct-line-measurement-3d/#unitOptions).
   */
  accessor unit: SystemOrLengthUnit;
  /**
   * List of available units and unit systems (imperial, metric) that are shown in the component's dropdown.
   * By default, the following units are included: `metric`, `imperial`, `inches`, `feet`, `us-feet`, `yards`, `miles`, `nautical-miles`, `meters`, `kilometers`.
   * Possible [unit](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-direct-line-measurement-3d/#unit) values can only be a subset of this list.
   */
  accessor unitOptions: Array<SystemOrLengthUnit>;
  /**
   * The view associated with the component. 
   *   > **Note:** The recommended approach is to fully migrate applications to use map and scene components and avoid using MapView and SceneView directly. However, if you are migrating a large application from widgets to components, you might prefer a more gradual transition. To support this use case, the SDK includes this `view` property which connects a component to a MapView or SceneView. Ultimately, once migration is complete, the arcgis-direct-line-measurement-3d component will be associated with a map or scene component rather than using the `view` property.
   */
  accessor view: SceneView | undefined;
  /** Clears the current measurement. */
  clear(): Promise<void>;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /** Starts a new measurement. */
  start(): Promise<void>;
  /** Emitted when the value of a property is changed. Use this to listen to changes to properties. */
  readonly arcgisPropertyChange: import("@arcgis/lumina").TargetedEvent<this, { name: "analysis" | "state"; }>;
  /** Emitted when the component associated with a map or scene view is ready to be interacted with. */
  readonly arcgisReady: import("@arcgis/lumina").TargetedEvent<this, void>;
  readonly "@eventTypes": {
    arcgisPropertyChange: ArcgisDirectLineMeasurement3d["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisDirectLineMeasurement3d["arcgisReady"]["detail"];
  };
}