/// <reference path="../../index.d.ts" />
import type Graphic from "@arcgis/core/Graphic.js";
import type FormTemplate from "@arcgis/core/form/FormTemplate.js";
import type Map from "@arcgis/core/Map.js";
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ArcgisReferenceElement, IconName } from "../types.js";
import type { ValueChangeEvent, SubmitEvent, FeatureFormViewModelState } from "@arcgis/core/widgets/FeatureForm/FeatureFormViewModel.js";
import type { EditType } from "@arcgis/core/widgets/support/forms/types.js";
import type { HeadingLevel } from "@arcgis/core/widgets/support/types.js";
import type { Icon } from "@esri/calcite-components/components/calcite-icon";
import type { FeatureFormLayerUnion } from "@arcgis/core/widgets/FeatureForm/types.js";

export abstract class ArcgisFeatureForm extends LitElement {
  /**
   * 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-feature-form/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * When true, the component is visually withdrawn and cannot receive user interaction.
   *
   * @default false
   * @since 5.0
   */
  accessor disabled: boolean;
  /**
   * The edit type for the form, which determines the editing context and behavior.
   *
   * This property is used in two primary ways:
   *
   * 1. **Arcade Expressions Context**: When evaluating [Arcade expressions](https://developers.arcgis.com/javascript/latest/arcade/#form-calculation),
   * the value of this property is assigned to the `$editContext.editType` variable.
   *    This allows Arcade expressions to adapt their behavior based on the type of edit
   *    being performed (e.g., "INSERT", "UPDATE", "DELETE", or "NA").
   *
   * 2. **Layer Editing Capabilities**: This property is also used to determine whether
   *    the layer allows the specified type of edit. For example:
   *    - If `editType` is set to `"INSERT"` but the layer has `supportsAdd: false`,
   *      all inputs in the form will be read-only.
   *    - If `editType` is set to `"UPDATE"` but the layer has `supportsUpdate: false`,
   *      all inputs will also be read-only.
   *
   * This behavior applies regardless of whether a form template or Arcade expressions
   * are present. For instance:
   * - If a layer has `{ supportsAdd: true, supportsUpdate: false }` and no form template,
   *   setting `editType` to `"INSERT"` will allow the user to modify all fields, while
   *   setting it to `"UPDATE"` will make all fields read-only.
   * - If a form template is present with field elements that include `editableExpression`
   *   or `valueExpression`, the `editType` still determines whether the layer permits
   *   editing in the given context.
   *
   * @default "NA"
   * @since 4.33
   * @see [Arcade Form Calculation - profile variables](https://developers.arcgis.com/arcade/profiles/form-calculation/#profile-variables)
   */
  accessor editType: EditType;
  /**
   * The associated feature containing the editable attributes.
   * A common way to access this is via the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#hitTest)
   * or [SceneView's](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#hitTest) `hitTest()`
   * method.
   *
   * @example
   * // Check if a user clicked on an incident feature.
   * view.on("click", function(event) {
   *   view.hitTest(event).then(function(response) {
   *     // Display the attributes of selected incident feature in the form
   *     if (response.results[0].graphic && response.results[0].graphic.layer.id == "incidentsLayer") {
   *        formVM.feature = result.results[0].graphic
   *     }
   *   });
   * });
   */
  accessor feature: Graphic | null | undefined;
  /**
   * The associated [template](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/) used for the form.
   *
   * The [FormTemplate](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/) is used to configure how the form should display and set any associated properties for the form, e.g. title, description, field elements, etc.
   *
   * @since 4.16
   * @see [Sample - Update Feature Attributes](https://developers.arcgis.com/javascript/latest/sample-code/editing-groupedfeatureform/)
   * @see [Sample - Advanced Attribute Editing](https://developers.arcgis.com/javascript/latest/sample-code/editing-featureform-fieldvisibility/)
   * @example
   * // Create the Form template and pass in elements
   * const formTemplate = new FormTemplate({
   *   title: "Inspector report",
   *   description: "Enter all relevant information below",
   *   elements: [groupElement] // Add the grouped elements to the template
   * });
   *
   * // Add a new feature form with grouped fields
   * const form = new FeatureForm({
   *   container: "form",
   *   groupDisplay: "sequential", // only display one group at a time
   *   formTemplate: formTemplate // set it to template created above
   * });
   */
  accessor formTemplate: FormTemplate | null | undefined;
  /**
   * String indicating the
   * [groupDisplay](https://developers.arcgis.com/javascript/latest/references/core/widgets/FeatureForm/#groupDisplay) and how they will be displayed to the end user. This only applies if using [grouped field elements](https://developers.arcgis.com/javascript/latest/references/core/form/elements/GroupElement/) configured in the Editor's [layer infos](https://developers.arcgis.com/javascript/latest/references/core/widgets/Editor/types/#LayerInfo).
   *
   * **Possible Values**
   *
   * Value | Description |
   * ----- | ----------- |
   * all | All groups will be expanded.
   * sequential | A single group will be expanded at a time.
   *
   * @default "all"
   * @since 4.10
   * @see [Sample - Update Feature Attributes](https://developers.arcgis.com/javascript/latest/sample-code/editing-groupedfeatureform/)
   */
  accessor groupDisplay: "all" | "sequential";
  /**
   * Indicates the heading level to use for the [FormTemplate#title](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/#title) of the form.
   * By default, the title is rendered as a level 2 heading (e.g. `<h2>Form title</h2>`).
   * In addition, group element labels default to a level 3 heading (e.g. `<h3>Group element label</h3>`).
   * Depending on the component's placement
   * in your app, you may need to adjust this heading for proper semantics. This is
   * important for meeting accessibility standards.
   *
   * @default 2
   * @since 4.20
   * @see [Heading Elements](https://developer.mozilla.org/docs/Web/HTML/Element/Heading_Elements)
   * @example
   * // form title will render as an <h3>
   * // group element labels will render as an <h4>
   * featureForm.headingLevel = 3;
   */
  accessor headingLevel: HeadingLevel;
  /** @default false */
  accessor hideReadOnlyNotice: boolean;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @default "form-field"
   * @since 4.27
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  get icon(): Icon["icon"];
  set icon(value: IconName);
  /**
   * The component's default label.
   *
   * @since 4.11
   */
  accessor label: string;
  /**
   * Layer containing the editable feature attributes.
   * If this layer is not specified, it is the same as the
   * [graphic's layer](https://developers.arcgis.com/javascript/latest/references/core/Graphic/#layer).
   *
   * @example
   * const form = new FeatureForm({
   *   container: "formDiv", // HTML div
   *   layer: featureLayer // Feature layer
   * });
   */
  accessor layer: FeatureFormLayerUnion | null | undefined;
  /**
   * A map is required when the input [layer](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-feature-form/#layer) has a popupTemplate that contains [Arcade](https://developers.arcgis.com/arcade) expressions in [ExpressionInfo](https://developers.arcgis.com/javascript/latest/references/core/popup/ExpressionInfo/) or [ExpressionContent](https://developers.arcgis.com/javascript/latest/references/core/popup/content/ExpressionContent/) that may use the `$map` profile variable to access data from layers within a map. Without a map, expressions that use `$map` will throw an error.
   *
   * @default null
   * @see [Type system](https://developers.arcgis.com/arcade/guide/types/#featuresetcollection)
   * @see [Arcade Profiles: Popup](https://developers.arcgis.com/arcade/profiles/popup/)
   * @since 5.0
   * @example
   * ```
   * // The building footprints represent the buildings that intersect a clicked parcel
   * let buildingFootprints = Intersects($feature, FeatureSetByName($map, "Building Footprints"));
   * ```
   */
  accessor map: Map | null | 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 current state of the component.
   *
   * @default "disabled"
   */
  get state(): FeatureFormViewModelState;
  /**
   * The timezone displayed within the form. If `unknown`, it first checks if the  layer has a [FeatureLayer#preferredTimeZone](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#preferredTimeZone). If so, it displays this. If not, it will default to UTC.
   *
   * @since 4.28
   */
  accessor timeZone: string;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /** Returns all of the field values, regardless of update status. */
  getValues(): Promise<any>;
  /** Fires the submit event. */
  submit(): Promise<void>;
  "@setterTypes": {
    icon?: IconName;
  };
  /** 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: "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>;
  /** Fires when the [submit()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-feature-form/#submit) method is called. */
  readonly arcgisSubmit: import("@arcgis/lumina").TargetedEvent<this, SubmitEvent>;
  /** Fires when a field value is updated. */
  readonly arcgisValueChange: import("@arcgis/lumina").TargetedEvent<this, ValueChangeEvent>;
  readonly "@eventTypes": {
    arcgisPropertyChange: ArcgisFeatureForm["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisFeatureForm["arcgisReady"]["detail"];
    arcgisSubmit: ArcgisFeatureForm["arcgisSubmit"]["detail"];
    arcgisValueChange: ArcgisFeatureForm["arcgisValueChange"]["detail"];
  };
}