import type SpatialReference from "../../geometry/SpatialReference.js";
import type { JSONSupport } from "../../core/JSONSupport.js";
import type { ObjectId } from "../../views/types.js";
import type { SpatialReferenceProperties } from "../../geometry/SpatialReference.js";

export interface RelationshipQueryProperties extends Partial<Pick<RelationshipQuery, "cacheHint" | "gdbVersion" | "geometryPrecision" | "maxAllowableOffset" | "num" | "objectIds" | "orderByFields" | "outFields" | "relationshipId" | "returnGeometry" | "returnM" | "returnTrueCurves" | "returnZ" | "start" | "where">> {
  /**
   * The historic moment to query. This parameter applies only if the `supportsHistoricMoment`
   * on [FeatureLayer.capabilities](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#capabilities) property of the layer is set to `true`.
   */
  historicMoment?: (Date | number | string) | null;
  /**
   * The spatial reference for the returned geometry. If `outSpatialReference` is not defined, the
   * [View.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/views/View/#spatialReference) of the view is used.
   */
  outSpatialReference?: SpatialReferenceProperties | null;
}

/**
 * This class defines parameters for executing queries for related records from a layer.
 * Once a RelationshipQuery object's properties are defined, it can then be passed into the
 * [executeRelationshipQuery()](https://developers.arcgis.com/javascript/latest/references/core/rest/query/#executeRelationshipQuery) and
 * [FeatureLayer.queryRelatedFeatures()](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#queryRelatedFeatures)
 * methods, which will return [FeatureSets](https://developers.arcgis.com/javascript/latest/references/core/rest/support/FeatureSet/) grouped by source layer/table objectIds.
 *
 * @since 4.20
 * @see [query](https://developers.arcgis.com/javascript/latest/references/core/rest/query/)
 * @see [Sample - Query Related Features](https://developers.arcgis.com/javascript/latest/sample-code/query-related-features/)
 */
export default class RelationshipQuery extends JSONSupport {
  constructor(properties?: RelationshipQueryProperties);
  /**
   * Indicates if the service should cache the relationship query results. It only applies if the layer's
   * [capabilities.queryRelated.supportsCacheHint](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#capabilities) is set to `true`.
   * Use only for queries that have the same parameters every time the app is used.
   * Some examples of cacheable queries:
   * * Queries based on [preset input](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RelationshipQuery/#where), for example, a drop-down list of US states.
   *
   * @since 4.24
   */
  accessor cacheHint: boolean | null | undefined;
  /** Specify the geodatabase version to query. */
  accessor gdbVersion: string | null | undefined;
  /** Specify the number of decimal places for the geometries returned by the query operation. */
  accessor geometryPrecision: number;
  /**
   * The historic moment to query. This parameter applies only if the `supportsHistoricMoment`
   * on [FeatureLayer.capabilities](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#capabilities) property of the layer is set to `true`.
   */
  get historicMoment(): Date | null | undefined;
  set historicMoment(value: (Date | number | string) | null | undefined);
  /**
   * The maximum allowable offset used for generalizing geometries returned by the query operation.
   * The offset is in the units of `outSpatialReference`. If `outSpatialReference` is not defined, the
   * [View.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/views/View/#spatialReference) of the view is used.
   */
  accessor maxAllowableOffset: number;
  /**
   * The number of features to retrieve. This option should be used in conjunction with the [start property](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RelationshipQuery/#start). Use this to
   * implement paging (i.e. to retrieve "pages" of results when querying).
   *
   * If not provided, but an instance of Query has a `start` property, then the default value of `num` is 10.
   * If neither `num` nor `start` properties are provided, then the default value of `num` is equal to the
   * `maxRecordCount` of the service, which can be found at the REST endpoint of the FeatureLayer.
   */
  accessor num: number;
  /** An array of objectIds for the features in the layer/table being queried. */
  accessor objectIds: ObjectId[] | null | undefined;
  /**
   * One or more field names used to order the query results. Specify `ASC` (ascending) or `DESC`
   * (descending) after the field name to control the order. The default order is `ASC`.
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > If querying a [MapImageLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/), then `supportsAdvancedQueries` must be `true` on the service.
   * > For [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/), `FeatureLayer.capabilities.queryRelated.supportsOrderBy` must be `true`.
   *
   * @see [FeatureLayer.capabilities](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#capabilities)
   * @example query.orderByFields = ["STATE_NAME DESC"];
   */
  accessor orderByFields: string[] | null | undefined;
  /**
   * Attribute fields to include in the FeatureSet. Fields must exist in the map layer. You must list actual
   * field names rather than the alias names. You are, however, able to use the alias names when you display
   * the results.
   *
   * When specifying the output fields, you should limit the fields to only those you expect to use in the
   * query or the results. The fewer fields you include, the faster the response will be.
   *
   * Each query must have access to the Shape and ObjectId fields for a layer. However, your list of fields does
   * not need to include these two fields.
   *
   * @example query.outFields = [ "NAME", "STATE_ABBR", "POP04" ];
   */
  accessor outFields: string[] | null | undefined;
  /**
   * The spatial reference for the returned geometry. If `outSpatialReference` is not defined, the
   * [View.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/views/View/#spatialReference) of the view is used.
   */
  get outSpatialReference(): SpatialReference | null | undefined;
  set outSpatialReference(value: SpatialReferenceProperties | null | undefined);
  /**
   * The ID of the relationship to be queried. The ids for the relationships the table or layer participates in are listed in the
   * ArcGIS Services directory.
   * The ID of the relationship to be queried. The relationships that this layer/table participates in are included in the Feature Service Layer resource response. Records in tables/layers corresponding to the related table/layer of the relationship are queried.
   */
  accessor relationshipId: number;
  /**
   * If `true`, each feature in the [FeatureSet](https://developers.arcgis.com/javascript/latest/references/core/rest/support/FeatureSet/) includes the geometry. Set to `false` (default)
   * if you do not plan to include highlighted features on a map since the geometry makes up a significant portion of the response.
   *
   * @default false
   */
  accessor returnGeometry: boolean;
  /** If `true`, and [returnGeometry](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RelationshipQuery/#returnGeometry) is `true`, then m-values are included in the geometry. */
  accessor returnM: boolean;
  /**
   * When `true` output geometry will include curves. If `false`, curves (if any) will be converted to
   * densified polylines or polygons.
   *
   * This option only applies when [returnGeometry](#returnGeometry) is set to `true` and the output geometry is
   * non-quantized polylines or polygons.
   *
   * @since 5.0
   * @see [ArcGIS REST API | Query Related Records | returnTrueCurves](https://developers.arcgis.com/rest/services-reference/enterprise/query-related-records-feature-service/#:~:text=returntruecurves)
   */
  accessor returnTrueCurves: boolean | null | undefined;
  /** If `true`, and [returnGeometry](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RelationshipQuery/#returnGeometry) is `true`, then z-values are included in the geometry. */
  accessor returnZ: boolean;
  /**
   * The zero-based index indicating where to begin retrieving features. This property should be used in conjunction with [num](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RelationshipQuery/#num).
   * Use this to implement paging and retrieve "pages" of results when querying. Features are sorted ascending by
   * object ID by default.
   */
  accessor start: number;
  /**
   * The definition expression to be applied to the related table or layer. Only records in the list of [objectIds](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RelationshipQuery/#objectIds)
   * that satisfy the definition expression are queried for related records.
   */
  accessor where: string | null | undefined;
  /**
   * Creates a deep clone of RelationshipQuery object.
   *
   * @returns A new instance of a RelationshipQuery object equal to the object used to call `.clone()`.
   */
  clone(): RelationshipQuery;
}