import type Graphic from "../../Graphic.js";
import type GraphicsLayer from "../../layers/GraphicsLayer.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { MapViewOrSceneView } from "../../views/MapViewOrSceneView.js";

/**
 * Options used by [openEditingSession()](https://developers.arcgis.com/javascript/latest/references/core/applications/Urban/editingSessionUtils/#openEditingSession).
 *
 * @internal
 * @internal
 */
export interface OpenEditingSessionOptions extends AbortOptions {
  /**
   * Temporary graphics layer where the editing graphic will be displayed during the session.
   *
   * @internal
   */
  graphicsLayer: GraphicsLayer;
  /**
   * Graphic to edit in the session.
   *
   * @internal
   */
  graphic: Graphic;
  /**
   * View where the editing session is opened.
   *
   * @internal
   */
  view: MapViewOrSceneView;
}

/**
 * Handle returned by [openEditingSession()](https://developers.arcgis.com/javascript/latest/references/core/applications/Urban/editingSessionUtils/#openEditingSession).
 *
 * Includes the queried editing graphic and disposal helpers that restore
 * source feature visibility.
 *
 * @internal
 * @internal
 */
export interface EditingSession extends AsyncDisposable {
  /**
   * Fully queried graphic used during the editing session.
   *
   * @internal
   */
  graphic: Graphic;
  /**
   * Closes the editing session and waits for the view to settle.
   *
   * @internal
   */
  remove(): Promise<void>;
  /**
   * Closes the editing session and waits for the view to settle when used with `await using`.
   *
   * @internal
   */
  [Symbol.asyncDispose](): Promise<void>;
}

/**
 * Opens a temporary editing session for a feature graphic.
 *
 * The function queries the full feature by object ID, updates the symbol to
 * match current display conditions, and swaps visibility so edits are shown on
 * a temporary graphic in `graphicsLayer`.
 *
 * @param options - Options for opening the editing session.
 * @returns A session handle with the editing graphic and cleanup methods.
 * @example
 * ```ts
 * const session = await openEditingSession({
 *   graphicsLayer,
 *   graphic,
 *   view,
 *   signal,
 * });
 *
 * try {
 *   editHandles.attach(session.graphic);
 * } finally {
 *   await session.remove();
 * }
 * ```
 * @example
 * ```ts
 * // The session has a `Symbol.asyncDispose` method that can be used with `await using` to ensure proper cleanup.
 * await using session = await openEditingSession({ graphicsLayer, graphic: partialGraphic, view });
 * ```
 * @internal
 * @internal
 */
export function openEditingSession(options: OpenEditingSessionOptions): Promise<EditingSession>;