/**
 * Provides utility functions for the [WFSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WFSLayer/).
 *
 * @since 4.20
 * @see [WFSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WFSLayer/)
 */
import type Extent from "../../geometry/Extent.js";
import type SpatialReference from "../../geometry/SpatialReference.js";
import type Field from "../support/Field.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { FeatureGeometryType } from "../../geometry/types.js";
import type { CustomParameters } from "../mixins/CustomParametersMixin.js";

export interface GetCapabilitiesOptions extends AbortOptions {
  /** A list of key-value pairs of parameters to append to the url. */
  customParameters?: CustomParameters | null;
}

/**
 * Fetches the GetCapabilities document of a WFS service which contains information about the
 * list of layers in the service and the available operations.
 *
 * @param url - The URL to the WFS endpoint.
 * @param options
 * @returns The WFS Capabilities for the service.
 * @example
 * const capabilities = await wfsUtils.getCapabilities(url);
 * const layerInfo = await wfsUtils.getWFSLayerInfo(capabilities, "layer");
 *
 * const layer = WFSLayer.fromWFSLayerInfo(layerInfo);
 *
 * // Same as
 * const layer = WFSLayer({
 *   url,
 *   name: "layer"
 * });
 */
export function getCapabilities(url: string, options?: GetCapabilitiesOptions): Promise<WFSCapabilities>;

/**
 * WFS service information about the available layers and operations.
 *
 * @see [getCapabilities()](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wfsUtils/#getCapabilities)
 * @see [getWFSLayerInfo()](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wfsUtils/#getWFSLayerInfo)
 */
export interface WFSCapabilities {
  /** Information about the operations needed to consume the WFS service. */
  readonly operations: WFSOperations;
  /** An array of featureTypes (or layers) available in the WFS service. */
  readonly featureTypes: Array<WFSFeatureType>;
}

/**
 * Information about some operations of the WFS service.
 *
 * @see [WFSCapabilities](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wfsUtils/#WFSCapabilities)
 */
export interface WFSOperations {
  GetCapabilities: WFSOperationsGetCapabilities;
  DescribeFeatureType: WFSOperationsDescribeFeatureType;
  GetFeature: WFSOperationsGetFeature;
}

export interface WFSOperationsGetCapabilities {
  /** The URL to the GetCapabilities endpoint. */
  url: string;
}

export interface WFSOperationsDescribeFeatureType {
  /** The URL to the DescribeFeatureType endpoint. */
  url: string;
}

export interface WFSOperationsGetFeature {
  /** The URL to the GetFeature endpoint. */
  url: string;
  /** Value of the geojson-like output format parameter (if any) to send with the GetFeature call. */
  outputFormat: string | null;
  /** Indicates if the GetFeature request supports pagination. */
  supportsPagination: boolean;
}

/**
 * Provides information about an individual feature type, or layer, found in the WFS service.
 *
 * @see [WFSCapabilities](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wfsUtils/#WFSCapabilities)
 */
export interface WFSFeatureType {
  /** The type name of the featureType. This will be of the format `namespacePrefix:name`. */
  typeName: `${string}:${string}`;
  /** The name of the featureType. */
  name: string;
  /** The title of the featureType. */
  title: string;
  /** The description of the featureType. */
  description: string;
  /** The extent of the features. */
  extent?: Extent | null;
  /** The prefix of the namespace. */
  namespacePrefix: string;
  /** The namespaceUri of the featureType. */
  namespaceUri: string;
  /** the default spatialReference wkid used when not explicitely specified in the GetFeature call. */
  defaultSpatialReference: number;
  /** An array of spatialReference wkids that are supported on the featureType. */
  supportedSpatialReferences: number[];
}

export interface WFSLayerInfoOptions extends AbortOptions {
  /** The desired spatial reference for the layer. By default will use the default spatial reference of the feature type. */
  spatialReference?: SpatialReference;
  /** A list of key-value pairs of parameters to append to the url. */
  customParameters?: CustomParameters | null;
}

/**
 * The layer info from the WFS service.
 *
 * @see [getWFSLayerInfo()](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wfsUtils/#getWFSLayerInfo)
 */
export interface WFSLayerInfo {
  /** The URL to the WFS service. */
  url: string;
  /** The name of the layer in the WFS service to display. */
  name: string;
  /** The namespace URI for the layer name. */
  namespaceUri: string;
  /** The fields on the layer. */
  fields: Field[];
  /** The geometry type of the features in the layer. */
  geometryType: FeatureGeometryType;
  /** The field containing the object ID. */
  objectIdField: string;
  /** The spatial reference of the layer. */
  spatialReference: SpatialReference;
  /** The extent of the layer. */
  extent?: Extent | null;
  /** Determines whether the X and Y coordinates should be swapped. */
  swapXY: boolean;
  wfsCapabilities: WFSCapabilities;
  /** The custom parameters applied to the layer. */
  customParameters?: CustomParameters | null;
}

/**
 * Returns the [WFSLayerInfo](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wfsUtils/#WFSLayerInfo) from the capabilities of the WFS service. Can be used in conjunction with getCapabilities
 *
 * @param capabilities - The capabilities of the WFS service.
 * @param name - The type name to get information for. If not specified, the first layer of the service is chosen.
 * @param namespaceUri - The namespace URI of the type name. If not specified, the first namespace found for the `name` is chosen.
 * @param options - An object specifying additional options. See the
 *   object specification table below for the required properties of this object.
 * @returns The layer info that can be used to create a [WFSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WFSLayer/)
 * @example
 * const capabilities = await wfsUtils.getCapabilities(url);
 * const layerInfo = await wfsUtils.getWFSLayerInfo(capabilities, "layer");
 *
 * const layer = WFSLayer.fromWFSLayerInfo(layerInfo);
 *
 * // Same as
 * const layer = WFSLayer({
 *   url,
 *   name: "layer"
 * });
 */
export function getWFSLayerInfo(capabilities: WFSCapabilities, name?: string | null, namespaceUri?: string | null, options?: WFSLayerInfoOptions): Promise<WFSLayerInfo>;