import type { JSONSupport } from "../../core/JSONSupport.js";
import type { FormElementType } from "../../portal/jsonTypes.js";

export interface ElementProperties extends Partial<Pick<Element, "description" | "label" | "visibilityExpression">> {}

/**
 * Form elements define what should display within the [FormTemplate](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/) elements.
 * There are five specific element types:
 *
 * * [FieldElement](https://developers.arcgis.com/javascript/latest/references/core/form/elements/FieldElement/)
 * * [GroupElement](https://developers.arcgis.com/javascript/latest/references/core/form/elements/GroupElement/)
 * * [RelationshipElement](https://developers.arcgis.com/javascript/latest/references/core/form/elements/RelationshipElement/)
 * * [TextElement](https://developers.arcgis.com/javascript/latest/references/core/form/elements/TextElement/)
 * * [UtilityNetworkAssociationsElement](https://developers.arcgis.com/javascript/latest/references/core/form/elements/UtilityNetworkAssociationsElement/)
 *
 * The `Element` class is a read-only base class which has no constructor.
 *
 * @since 4.16
 */
export default abstract class Element extends JSONSupport {
  /** The element's description providing the purpose behind it. */
  accessor description: string | null | undefined;
  /** A string value containing the field alias. This should not be used for referencing fields in Arcade expressions. Rather, the service [FieldElement.fieldName](https://developers.arcgis.com/javascript/latest/references/core/form/elements/FieldElement/#fieldName) should be referenced. */
  accessor label: string | null | undefined;
  /**
   * The type of form element to display.
   *
   * Possible Value | Description
   * ---------------|-------------
   * field | An individual [field](https://developers.arcgis.com/javascript/latest/references/core/form/elements/FieldElement/) element that defines the field within a layer or [form's](https://developers.arcgis.com/javascript/latest/references/core/widgets/FeatureForm/#formTemplate) `formTemplate`.
   * group | Contains a [grouping](https://developers.arcgis.com/javascript/latest/references/core/form/elements/GroupElement/) of [field](https://developers.arcgis.com/javascript/latest/references/core/form/elements/FieldElement/) elements.
   * relationship | A [relationship](https://developers.arcgis.com/javascript/latest/references/core/form/elements/RelationshipElement/) element defines a relationship between [Map.layers](https://developers.arcgis.com/javascript/latest/references/core/Map/#layers) and [Map.tables](https://developers.arcgis.com/javascript/latest/references/core/Map/#tables) and how they participate in the [FeatureForm](https://developers.arcgis.com/javascript/latest/references/core/widgets/FeatureForm/).
   * text | A [text](https://developers.arcgis.com/javascript/latest/references/core/form/elements/TextElement/) element defines descriptive text in a [FormTemplate](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/).
   * utilityNetworkAssociations | A [utilityNetworkAssociations](https://developers.arcgis.com/javascript/latest/references/core/form/elements/UtilityNetworkAssociationsElement/) element defines how utility network associations participate in the form.
   */
  get type(): FormElementType;
  /**
   * A reference to the [ExpressionInfo.name](https://developers.arcgis.com/javascript/latest/references/core/form/ExpressionInfo/#name) of an
   * [Arcade](https://developers.arcgis.com/javascript/latest/arcade/) expression defined in the
   * [FormTemplate.expressionInfos](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/#expressionInfos) of the [FormTemplate](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/).
   *
   * When this expression evaluates to `true`, the element is displayed. When the expression evaluates to `false` the element is not displayed. If no expression
   * is provided, the element is always displayed.
   * Care must be taken when defining a visibility expression for a non-nullable
   * field as to make certain the specified field has either 1) a default value, or 2) is made visible to the end user to enter a value before submitting the form.
   *
   * > [!WARNING]
   * >
   * > The expression must follow the specification
   * > defined in the [Form Calculation Profile](https://developers.arcgis.com/javascript/latest/arcade/#form-calculation). This expression references field values within an individual feature or in other layers and must return either a date, number, or string value.
   * > The referenced expression must be defined in the form template's [FormTemplate.expressionInfos](https://developers.arcgis.com/javascript/latest/references/core/form/FormTemplate/#expressionInfos).
   * > It cannot be set inline within the element object.
   * > [Field](https://developers.arcgis.com/javascript/latest/references/core/form/elements/FieldElement/) and [Group](https://developers.arcgis.com/javascript/latest/references/core/form/elements/GroupElement/) elements must be visible if the field or one of the grouped fields is [required](https://developers.arcgis.com/javascript/latest/references/core/form/elements/FieldElement/#requiredExpression).
   *
   * @see [ExpressionInfo](https://developers.arcgis.com/javascript/latest/references/core/form/ExpressionInfo/)
   * @see [Sample - Update Feature Attributes](https://developers.arcgis.com/javascript/latest/sample-code/editing-groupedfeatureform/)
   * @see [Form Constraint Arcade Profile](https://developers.arcgis.com/javascript/latest/arcade/#constraint)
   * @example
   * // Expression created within ExpressionInfos and is referenced in element
   * const expression = new ExpressionInfo({
   *   name: "alwaysHidden",
   *   expression: "false"
   * });
   *
   * // Reference an already-defined visibilityExpression set within the ExpressionInfos
   * const fieldElement = new FieldElement({
   *   type: "field",
   *   fieldName: "inspemail",
   *   label: "Email address",
   *   visibilityExpression: "alwaysHidden"
   * });
   *
   * formTemplate.expressionInfos = [ expression ];
   * formTemplate.elements = [ fieldElement ];
   */
  accessor visibilityExpression: string | null | undefined;
}