import type Field from "./Field.js";

/**
 * This class provides convenient methods that can be used to make
 * case-insensitive lookups for a field by its name.
 * It also provides more information such as the list
 * of [date fields](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FieldsIndex/#dateFields) in a layer.
 *
 * @since 4.12
 */
export default class FieldsIndex<T extends Field = Field> {
  constructor(fields?: T[] | null | undefined);
  /**
   * An array of date fields or field json objects.
   *
   * @default []
   */
  readonly dateFields: T[];
  /**
   * Returns a field with the specified field name.
   *
   * @param fieldName - The name of the field. The name is case-insensitive.
   * @returns Returns a field with a given name.
   */
  get(fieldName: string | null | undefined): T | null | undefined;
  /**
   * Returns a [time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a field.
   * Use this method to ensure queries in the following places are issued in the time zone of the given `date` field:
   * * [FeatureLayer.definitionExpression](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#definitionExpression)
   * * [Query.where](https://developers.arcgis.com/javascript/latest/references/core/rest/support/Query/#where)
   * * [FeatureFilter.where](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureFilter/#where)
   *
   * The following table explains the value returned from this method:
   *
   * | Field type | Returned value |
   * | ---------- | -------------- |
   * | Date field | Returns the time zone associated with the date field. Returns `unknown` if the layer's date fields are in [unknown time zone](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#datesInUnknownTimezone).|
   * | Date-only, Time-only or Timestamp-offset field | Returns `unknown` as services do not have time zone associated with `date-only`, `time-only` and `timestamp-offset` fields. Date-only and time-only fields are time zone agnostic. Timestamp-offset field values store its time offset. |
   * | All other fields | Returns `null`. |
   *
   * @param fieldOrFieldName - The name of the field or the field instance.
   * @returns Returns the [time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the given date field name or date field instance.
   * @see [REST API - Date-time queries](https://developers.arcgis.com/rest/services-reference/enterprise/query-feature-service-layer/#date-time-queries)
   * @see [Date and time queries](https://developers.arcgis.com/javascript/latest/references/core/rest/support/Query/#date-query)
   * @example
   * // Query for features that recorded on January 1, 2012 9:00:00 AM GMT
   * // DateTime_PST date field values are in PST. Must adjust the epoch values to PST
   *
   * const queryDate = new Date(1325408400000); 01/01/2012 9:00:00 AM GMT
   * let queryFields = ["DateTime_PST"];
   *
   * // get the timezone of the DateTime_PST date field
   * const fieldTimeZone = layer.fieldsIndex.getTimeZone("DateTime_PST") ;
   *
   * // we need to adjust the date value to match the time zone of the field.
   * const where = `DateTime_PST < DATE '${getDateForTimeZone(queryDate, fieldTimeZone)}'`
   * layerView.filter = new FeatureFilter({
   *   where
   * });
   * runQueries(where, queryFields);
   *
   * // This function conveniently formats a date in terms of the parsed time zone.
   * function getDateForTimeZone(queryDate, timezone) {
   *
   *   // adjust the given date field to the timezone of the date field
   *   const zonedDate = new Date(
   *     queryDate.toLocaleString("en-US", {
   *       timeZone: timezone
   *     })
   *   );
   *   const pad = (value) => String(value).padStart(2, "0");
   *   const month = pad(zonedDate.getMonth() + 1);
   *   const day = pad(zonedDate.getDate())
   *   const year = zonedDate.getFullYear();
   *   const hour = pad(zonedDate.getHours());
   *   const minutes = pad(zonedDate.getMinutes());
   *   const seconds = pad(zonedDate.getSeconds());
   *
   *   return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}`;
   * }
   */
  getTimeZone(fieldOrFieldName: T | string | null | undefined): string | null | undefined;
  /**
   * Checks if a field with the specified field name exists in the layer.
   *
   * @param fieldName - The name of the field. The name is case-insensitive.
   * @returns Returns `true` if the field exists otherwise returns `false`.
   */
  has(fieldName: string): boolean;
  /**
   * Checks if a field with the specified field name is a date field.
   *
   * @param fieldName - The name of the field.
   * @returns Returns `true` if the field type is date otherwise returns `false`.
   */
  isDateField(fieldName: string | null | undefined): boolean;
}