import type Graphic from "../../Graphic.js";
import type EsriMap from "../../Map.js";
import type Collection from "../../core/Collection.js";
import type BatchFormInputs from "./inputs/BatchFormInputs.js";
import type FieldInput from "./inputs/FieldInput.js";
import type { EventedAccessor, EventedMixinProperties } from "../../core/Evented.js";
import type { FieldValue } from "../../layers/support/fieldUtils.js";
import type { TimeZone } from "../../time/types.js";
import type { AttributeFormSupportedLayerInfo, AttributeFormSupportedLayerUnion, BatchAttributeFormMode, BatchAttributeFormState, ValueChangeEvent, SubmitEvent } from "./types.js";
import type { FormInput } from "./inputs/types.js";
import type { EditType } from "../support/forms/types.js";

export interface BatchAttributeFormViewModelProperties extends EventedMixinProperties, Partial<Pick<BatchAttributeFormViewModel, "activeFeatureIndex" | "disabled" | "editType" | "features" | "layerInfos" | "map" | "readOnly" | "sharedForm" | "submitHasBeenAttempted" | "timeZone" | "userHasChangedValues">> {}

export interface BatchAttributeFormViewModelEvents {
  /** Fires when the [BatchAttributeForm#submit()](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm.html#submit) method is called. */
  submit: SubmitEvent;
  /** Fires when field values are updated. */
  "value-change": ValueChangeEvent;
}

/**
 * Provides the logic for the [BatchAttributeForm](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm.html) widget.
 *
 * > [!WARNING]
 * >
 * > **Known Limitations**
 * >
 * > Currently, editing [relationship elements](https://developers.arcgis.com/javascript/latest/api-reference/esri-form-elements-RelationshipElement.html) and [Attachments](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Attachments.html) and are not supported within this widget. Users can edit related records and attachments individually using the [FeatureForm](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureForm.html) widget.
 * > Editing utility network associations is not supported within this widget. Users can edit association fields individually using the [FeatureForm](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureForm.html) widget.
 * > [Text elements](https://developers.arcgis.com/javascript/latest/api-reference/esri-form-elements-TextElement.html) are not supported within this widget.
 * > The widget does not support editing features from layers with contingent values.
 *
 * @since 4.33
 * @see [Editor](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Editor.html)
 * @see [BatchAttributeForm](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm.html)
 * @example
 * let batchAttributeForm = new BatchAttributeForm({
 *   viewModel: { // Autocasts as new BatchAttributeFormViewModel()
 *     map: map, // Required if using Arcade expressions that use the global $map variable
 *     features: featureCollection,
 *   },
 *   container: "batchAttributeFormDiv"
 * });
 */
export default class BatchAttributeFormViewModel extends EventedAccessor {
  /**
   * @deprecated
   * Do not directly reference this property.
   * Use EventNames and EventTypes helpers from \@arcgis/core/Evented
   */
  "@eventTypes": BatchAttributeFormViewModelEvents;
  constructor(properties?: BatchAttributeFormViewModelProperties);
  /** The active feature in the form, which is the feature that is currently being edited while in `single`[mode](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#mode). If the `mode` is `batch`, this property will be `null`. */
  get activeFeature(): Graphic | null | undefined;
  /**
   * The index of the active feature that is currently being edited. This will be `-1` when [mode](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#mode) is `batch`.
   * To enter `single` mode, set this property to the index in the [features](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#features) array of the feature you wish to edit individually. To enter `batch` mode, set this property to `-1`.
   *
   * @default -1
   */
  accessor activeFeatureIndex: number;
  /**
   * Returns the [batch attribute form inputs](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-inputs-BatchFormInputs.html) that are currently being edited. This is
   * dependent on the form's [mode](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#mode). If the [mode](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#mode) is
   * `batch`, it returns the [shared form](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#sharedForm) inputs. If `single`, it
   * returns the form inputs for the [active feature](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#activeFeature).
   * This property is read-only and should not be modified directly.
   * To change which form is active, see [activeFeatureIndex](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#activeFeatureIndex).
   */
  get activeForm(): BatchFormInputs;
  /**
   * Indicates whether the form is currently evaluating Arcade expressions.
   * This is `true` when the form is evaluating expressions or
   * when it is waiting for a response from the server.
   */
  get calculating(): boolean;
  /**
   * Indicates whether the associated view should be in `read-only` mode.
   * When `true`, the associated view should display the form in a read-only
   * mode, disabling any editing.
   *
   * @default false
   */
  accessor disabled: boolean;
  /**
   * The type of edit operation the form is being used for. This can influence
   * whether a field is editable or not (e.g., the layer only allows certain
   * edit operations), and it is the value used for the `$editcontext.editType`
   * variable when evaluating Arcade expressions. The value "NA" is always
   * allowed when determining if a layer allows the current edit type.
   *
   * @default "NA"
   * @see [Arcade Form Calculation - profile variables](https://developers.arcgis.com/arcade/profiles/form-calculation/#profile-variables)
   */
  accessor editType: EditType;
  /**
   * Indicates whether any of the Arcade expressions in the form have
   * failed to evaluate.
   */
  get expressionEvaluationFailed(): boolean;
  /**
   * The collection of features whose attributes are being edited.
   * This collection should be treated as immutable. Adding, removing, or re-ordering features is not allowed and may yield unexpected results. You can assign a new collection to this property, but this will cause the form inputs to be re-generated and any modified values to be discarded.
   */
  accessor features: Collection<Graphic>;
  /**
   * Indicates whether the form has too many features to be loaded
   * with forms containing complex [Arcade](https://developers.arcgis.com/javascript/latest/arcade/) expressions.
   */
  get hasTooManyComplexFeatures(): boolean;
  /** Indicates whether the form has too many features to be loaded. */
  get hasTooManyFeatures(): boolean;
  /**
   * Indicates whether there are any visible inputs in the form.
   * This is `true` if there are any inputs that are visible to the user, meaning they are not hidden by a visibility expression or group visibility expression.
   */
  get hasVisibleInputs(): boolean;
  /** Returns an array of features that are invalid, meaning they have at least one invalid attribute value. */
  get invalidFeatures(): Graphic[];
  /**
   * An array of objects containing a [FormTemplate](https://developers.arcgis.com/javascript/latest/api-reference/esri-form-FormTemplate.html) and its corresponding layer.
   * This provides a way to configure a `FormTemplate` with the supported field elements in `BatchAttributeForm`.
   *
   * @see [Map#editableLayers](https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html#editableLayers)
   * @example
   * // Query for features
   * const { features } = await featureLayer.queryFeatures();
   *
   * // Initialize BatchAttributeFormViewModel
   * const batchAttributeFormViewModel = new BatchAttributeFormViewModel({
   *   features: features,
   *   layerInfos: [{
   *     layer: featureLayer,
   *     formTemplate:  { // autocasts to FormTemplate
   *       elements: [
   *         { // autocasts to FieldElement
   *           type: "field",
   *           fieldName: "fulladdr",
   *           label: "Full Address"
   *         }
   *       ]
   *     },
   *   }]
   * });
   */
  accessor layerInfos: AttributeFormSupportedLayerInfo[] | null | undefined;
  /**
   * An array of layers included in the batch attribute form. Each layer must support feature editing and field access.
   *
   * The following layer types are supported:
   * - [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html)
   * - [GeoJSONLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GeoJSONLayer.html)
   * - [SceneLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-SceneLayer.html) (with `featureLayer` property)
   * - [SubtypeSublayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-SubtypeSublayer.html)
   * - [OrientedImageryLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-OrientedImageryLayer.html)
   * - [KnowledgeGraphSublayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-knowledgeGraph-KnowledgeGraphSublayer.html)
   */
  get layers(): AttributeFormSupportedLayerUnion[];
  /**
   * A reference to the associated [Map](https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html).
   *
   * > [!WARNING]
   * >
   * > This property is required if working with [Arcade expressions](https://developers.arcgis.com/javascript/latest/arcade/) in the `BatchAttributeForm` that make use of the `$map` global variable.
   */
  accessor map: EsriMap | null | undefined;
  /**
   * The mode of the form, which can be either `"single"` or `"batch"`.
   * In `"single"` mode, the form is editing a single feature at a time, while in
   * `"batch"` mode, it is editing all of the features in the [features](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#features) collection. To change the mode, set the [activeFeatureIndex](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#activeFeatureIndex) property.
   *
   * @default "batch"
   */
  get mode(): BatchAttributeFormMode;
  /**
   * Indicates whether the form is in a read-only state. When `true`, the user
   *  cannot modify any attribute values in the form. This is different from
   *  [disabled](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#disabled), which indicates whether the entire form is
   *  disabled, including any UI controls.
   *
   * @default false
   */
  accessor readOnly: boolean;
  /** The set of form inputs used in `batch` editing [mode](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#mode). */
  accessor sharedForm: BatchFormInputs;
  /**
   * Indicates whether the view model is ready to be used. Upon construction,
   * and then again any time the `features` Collection is modified or
   * re-assigned, the view model must perform certain asynchronous tasks in
   * order to compile the shared attribute form. Use the `status` property to
   * determine when this processing occurs.
   *
   * Value | Description
   * ------|------------
   * not-loaded | The [features](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#features) property has not been initialized or is an empty [Collection](https://developers.arcgis.com/javascript/latest/api-reference/esri-core-Collection.html).
   * loading | The [features](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#features) property has been set or modified, and the view model is compiling the shared form. Certain properties, like [activeForm](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#activeForm), should not be accessed yet.
   * loaded | The view model is ready to use.
   * failed | An error occurred while compiling the shared form.
   */
  get status(): BatchAttributeFormState;
  /**
   * Indicates whether the user has attempted to submit the form.
   *
   * @default false
   */
  accessor submitHasBeenAttempted: boolean;
  /** The time zone used to interpret date values in the form. If this property is `null` or set to `"unknown"`, date values are displayed in the time zone specified by the layer's [FeatureLayer#preferredTimeZone](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#preferredTimeZone). If none is provided there, date values are interpreted in UTC. */
  accessor timeZone: TimeZone | null | undefined;
  /**
   * Indicates whether any values, for any features, have been modified by the
   * user. This property does not take into account changes to attribute values
   * that resulted from calculated value expressions.
   *
   * @default false
   */
  accessor userHasChangedValues: boolean;
  /**
   * Indicates whether there are any validation errors for any fields for any
   * features.
   */
  get valid(): boolean;
  /**
   * An array of visible inputs in the active form. This is a subset of the
   * inputs that are currently being edited, filtered to only include those that
   * are visible to the user.
   */
  get visibleInputs(): FormInput[];
  /**
   * Convenience method to find field inputs. Gets field inputs from the _activeFormInputsByElementId cache if there is one
   *
   * @param elementId - The elementId of the input field to find.
   * @returns Returns an instance of the FieldInput.
   */
  findFieldInput(elementId: string | null | undefined): FieldInput | null | undefined;
  /**
   * The method used to get the updated field value.
   *
   * @param elementId - The id of the target field where the value is accessed.
   * @returns Returns the associated field value, or `undefined` if there is no matching attribute.
   */
  getFieldInputValue(elementId: string): FieldValue | undefined;
  /**
   * This method triggers the `"submit"` event, and causes [submitHasBeenAttempted](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BatchAttributeForm-BatchAttributeFormViewModel.html#submitHasBeenAttempted) to become `true`. It does _not_ do anything to persist the updated values. It is up to the client these values as appropriate — for example, by calling [FeatureLayer#applyEdits()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#applyEdits) method to update the features' attributes.
   *
   * @example
   * // Listen for when 'submit' is called on the form.
   * // Once it is fired, update the feature.
   * batchAttributeForm.on("submit", updateFeature);
   * // When the DOM's button (btnUpdate) is clicked,
   * // execute the 'submit()' method.
   * on(dom.byId("btnUpdate"), "click", form.submit());
   */
  submit(): void;
}