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

/**
 * The Line Of Sight component is a 3D analysis tool that allows you to perform
 * [line of sight visibility analysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/LineOfSightAnalysis/)
 * in an [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/). Visibility between a given observer and multiple target points is calculated against the currently
 * displayed content in the view, including the ground, integrated meshes, and 3D objects such as buildings or trees.
 *
 * ![line-of-sight](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/line-of-sight.avif)
 *
 * The analysis results are displayed as colored lines, where areas visible to the observer are
 * shown green and occluded parts are marked in red. Also, the color of the target points indicates their visibility.
 * When the line of sight cannot be calculated, it will be displayed with a gray color. This may happen if either
 * the target or the observer is not in the view.
 *
 * When creating a new line of sight analysis, the first click in the Scene creates the
 * [observer](https://developers.arcgis.com/javascript/latest/references/core/analysis/LineOfSightAnalysisObserver/)
 * and subsequent clicks place the [targets](https://developers.arcgis.com/javascript/latest/references/core/analysis/LineOfSightAnalysisTarget/).
 * Both the observer and target points can be moved by dragging. Additionally, the target points can be removed with a right click.
 *
 * **Known limitation**
 *
 * Line Of Sight is only supported in a 3D [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/) component.
 *
 * **See also**
 *
 * - [LineOfSightAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/LineOfSightAnalysis/)
 * - [Sample - Line of sight component](https://developers.arcgis.com/javascript/latest/sample-code/line-of-sight/)
 * - [Sample - Analysis objects](https://developers.arcgis.com/javascript/latest/sample-code/analysis-objects/)
 *
 * @since 4.28
 */
export abstract class ArcgisLineOfSight extends LitElement {
  /** @internal */
  protected _messages: {
      componentLabel: string;
      hint: string;
      unsupported: string;
      done: string;
      newAnalysis: string;
      continueAnalysis: string;
  } & T9nMeta<{
      componentLabel: string;
      hint: string;
      unsupported: string;
      done: string;
      newAnalysis: string;
      continueAnalysis: string;
  }>;
  /**
   * The [LineOfSightAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/LineOfSightAnalysis/)
   * created or modified by the component.
   *
   * When connecting the Line Of Sight component to the [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 [LineOfSightAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/LineOfSightAnalysisView3D/)
   * to be created before accessing the analysis results.
   *
   * ```js
   * // Get the Scene component and the Line Of Sight component, and wait until both are ready.
   * const viewElement = document.querySelector("arcgis-scene");
   * await viewElement.viewOnReady();
   * const lineOfSightElement = document.querySelector("arcgis-line-of-sight");
   * await lineOfSightElement.componentOnReady();
   *
   * // Get the LineOfSightAnalysis created by the Line Of Sight component.
   * const analysis = lineOfSightElement.analysis;
   *
   * // Get the LineOfSightAnalysisView3D and watch for updates.
   * const analysisView = await viewElement.whenAnalysisView(analysis);
   * const handle = reactiveUtils.watch(
   *   () => analysisView?.results,
   *   () => {
   *     console.log("Analysis results:", analysisView.results);
   *   },
   * );
   * ```
   * Whenever the component is destroyed, the analysis is automatically removed from the collection.
   *
   * Alternatively, a programmatically created [LineOfSightAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/LineOfSightAnalysis/)
   * 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 LineOfSightAnalysis.
   * const lineOfSightAnalysis = new LineOfSightAnalysis({
   *   observer: new LineOfSightAnalysisObserver({
   *         position: new Point({
   *         spatialReference: { latestWkid: 3857, wkid: 102100 },
   *         x: -13624828.3377593,
   *         y: 4550305.319405007,
   *         z: 105.55410975124687
   *         }),
   *   }),
   *   targets: [ new LineOfSightAnalysisTarget({
   *         position: new Point({
   *         spatialReference: { latestWkid: 3857, wkid: 102100 },
   *         x: -13624944.17687458,
   *         y: 4550420.577689567,
   *         z: 0
   *         }),
   *   })
   * ]
   * });
   *
   * // Get the Scene component and the Line Of Sight component, and wait until both are ready.
   * const viewElement = document.querySelector("arcgis-scene");
   * await viewElement.viewOnReady();
   * const lineOfSightElement = document.querySelector("arcgis-line-of-sight");
   * await lineOfSightElement.componentOnReady();
   *
   * // Add the analysis to the analyses collection of the Scene component.
   * viewElement.analyses.add(lineOfSightAnalysis);
   *
   * // Connect the analysis to the component:
   * lineOfSightElement.analysis = lineOfSightAnalysis;
   * ```
   */
  accessor analysis: LineOfSightAnalysis;
  /**
   * 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-line-of-sight/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * If true, the button that allows the user to continue placing more targets.
   *
   * @default false
   * @since 5.0
   */
  accessor hideContinueButton: boolean;
  /**
   * If true, the button that ends the current placement will be hidden.
   *
   * @default false
   * @since 5.0
   */
  accessor hideDoneButton: boolean;
  /**
   * If true, the button that starts a new analysis will be hidden.
   *
   * @default false
   * @since 5.0
   */
  accessor hideStartButton: 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 "line-of-sight"
   * @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;
  /**
   * Replace localized message strings with your own strings.
   *
   * _**Note**: Individual message keys may change between releases._
   */
  accessor messageOverrides: {
      componentLabel?: string | undefined;
      hint?: string | undefined;
      unsupported?: string | undefined;
      done?: string | undefined;
      newAnalysis?: string | undefined;
      continueAnalysis?: string | undefined;
  };
  /**
   * 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 analysis
   * * `creating` - observer/target points are being placed
   * * `created` - finished analysis
   */
  get state(): "created" | "creating" | "disabled" | "ready";
  /**
   * 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-line-of-sight component will be associated with a map or scene component rather than using the `view` property.
   */
  accessor view: SceneView | undefined;
  /** Clear the current analysis results. After calling this method, the user can set a new observer and targets. */
  clear(): Promise<void>;
  /** After [stop()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-line-of-sight/#stop) was called, this method allows to continue the line of sight analysis and add more targets. */
  continue(): Promise<void>;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /** Start a new line of sight analysis. */
  start(): Promise<void>;
  /**
   * Stop the current placing of line of sight analysis. Any lines added this far are kept  in the view.
   * Users can still interact with existing targets and the observer, but they cannot place new target points.
   */
  stop(): 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: ArcgisLineOfSight["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisLineOfSight["arcgisReady"]["detail"];
  };
}