/**
 * Provides utility functions for the [WCSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WCSLayer/).
 *
 * @since 4.31
 * @see [WCSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WCSLayer/)
 */
import type Extent from "../../geometry/Extent.js";
import type Polygon from "../../geometry/Polygon.js";
import type RasterInfo from "../support/RasterInfo.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { CustomParameters } from "../mixins/CustomParametersMixin.js";
import type { PixelSize, RasterBandStatistics, RasterInterpolation } from "../raster/types.js";

/**
 * Fetches the capabilities metadata offered by the WCS service, including supported versions and coverages information.
 *
 * @param url - The URL to the WCS service endpoint.
 * @param options
 * @returns The WCS Capabilities for the service.
 * @example
 * const capabilities = await wcsUtils.getCapabilities(url);
 * // use capabilities information
 */
export function getCapabilities(url: string, options?: GetCapabilitiesOptions): Promise<WCSCapabilities>;

/** Capabilities metadata offered by the WCS service, including supported versions and coverages information. */
export interface GetCapabilitiesOptions extends AbortOptions {
  /** A list of key-value pairs of parameters to append to the url. */
  customParameters?: CustomParameters | null;
  /** The version of the WCS service. */
  version?: WCSVersion | null;
}

/** @since 5.0 */
export type WCSVersion = "1.0.0" | "1.1.0" | "1.1.1" | "1.1.2" | "2.0.1";

/**
 * Coverage information associated with a WCS service.
 *
 * @since 5.0
 */
export interface WCSCoverageBrief {
  /**
   * The id of the coverage.
   *
   * @since 5.0
   */
  id: string;
  /**
   * The extent of the coverage.
   *
   * @since 5.0
   */
  lonLatEnvelope?: Extent;
  /**
   * The subtype of the coverage.
   *
   * @since 5.0
   */
  coverageSubType?: string;
}

/**
 * A list of URLs for the WCS service resources. It is necessary for a WCS client to communicate correctly with your WCS service.
 *
 * @since 5.0
 */
export interface WCSOnlineResources {
  /**
   * The URL to the getCapabilities endpoint.
   *
   * @since 5.0
   */
  getCapabilities: string;
  /**
   * The URL to the describeCoverage endpoint.
   *
   * @since 5.0
   */
  describeCoverage: string;
  /**
   * The URL to the getCoverage endpoint.
   *
   * @since 5.0
   */
  getCoverage: string;
}

/**
 * WCS service information about the available coverages, versions, extensions and more.
 *
 * @since 5.0
 * @see [getCapabilities()](https://developers.arcgis.com/javascript/latest/references/core/layers/ogc/wcsUtils/#getCapabilities)
 */
export interface WCSCapabilities {
  /**
   * Name of the WCS service.
   *
   * @since 5.0
   */
  name: string;
  /**
   * Online resources for the WCS service.
   *
   * @since 5.0
   */
  onlineResources: WCSOnlineResources;
  /**
   * Information about the available coverages.
   *
   * @since 5.0
   */
  coverages: WCSCoverageBrief[];
  /**
   * Information about the available grid coverages.
   *
   * @since 5.0
   */
  gridCoverages: WCSCoverageBrief[];
  /**
   * The versions supported by the WCS service.
   *
   * @since 5.0
   */
  supportedVersions: string[];
  /**
   * The WCS service version.
   *
   * @since 5.0
   */
  version: WCSVersion;
  /**
   * Formats supported by the WCS service.
   *
   * @since 5.0
   */
  supportedFormats?: string[];
  /**
   * Application profiles supported by the WCS service.
   *
   * @since 5.0
   */
  profiles?: string[];
  /**
   * Interpolations supported by the WCS service.
   *
   * @since 5.0
   */
  supportedInterpolations?: string[];
}

/**
 * Coverage information associated with a WCS service. It returns information related to coordinate reference systems, spatial and range domains, and formats supported by a service.
 *
 * @since 4.26
 */
export interface WCSCoverageInfo {
  /**
   * Service coverage id.
   *
   * @since 5.0
   */
  id: string;
  /**
   * Service coverage title.
   *
   * @since 5.0
   */
  title: string;
  /**
   * Service coverage description.
   *
   * @since 5.0
   */
  description: string;
  /**
   * Coverage band names.
   *
   * @since 5.0
   */
  bandNames: string[];
  /**
   * Coverage raster info.
   *
   * @since 5.0
   */
  rasterInfo: RasterInfo;
  /**
   * Formats supported by a service.
   *
   * @since 5.0
   */
  supportedFormats: string[];
  /**
   * Coverage
   * description for different versions.
   *
   * @since 5.0
   */
  coverageDescription: WCSCoverageDescriptionV100 | WCSCoverageDescriptionV110 | WCSCoverageDescriptionV201;
  /**
   * The service version.
   *
   * @since 5.0
   */
  version: WCSVersion;
  /**
   * Indicates if the EPSG axis is used.
   *
   * @since 5.0
   */
  useEPSGAxis: boolean;
  /**
   * Spatial extent of the coverage.
   *
   * @since 5.0
   */
  lonLatEnvelope?: Extent;
  /**
   * Interpolation supported by a service.
   *
   * @since 5.0
   */
  supportedInterpolations?: RasterInterpolation[];
}

/** @since 5.0 */
export interface WCSRangeSet {
  /**
   * Range set name.
   *
   * @since 5.0
   */
  name: string;
  /**
   * Range set label.
   *
   * @since 5.0
   */
  label: string;
  /**
   * Provides additional information on compound valued range set.
   *
   * @since 5.0
   */
  axis: WCSRangeAxis[];
  /**
   * The null values is used when valid values are not available.
   *
   * @since 5.0
   */
  nullValues?: number[] | null;
}

/** @since 5.0 */
export interface WCSRangeAxis {
  /**
   * Range axis name.
   *
   * @since 5.0
   */
  name: string;
  /**
   * Range axis label.
   *
   * @since 5.0
   */
  label: string;
  /**
   * Range axis values.
   *
   * @since 5.0
   */
  values: string[];
}

/** @since 5.0 */
export interface WCSDomainSet {
  /**
   * Spatial domain of a coverage.
   *
   * @since 5.0
   */
  spatialDomain: WCSSpatialDomain;
  /**
   * Temporal domain or extent of a coverage.
   *
   * @since 5.0
   */
  temporalDomain?: WCSTemporalDomain | null;
}

/** @since 5.0 */
export interface WCSSpatialDomain {
  /**
   * Spatial domain extent.
   *
   * @since 5.0
   */
  envelope: Extent;
  /**
   * Spatial domain columns.
   *
   * @since 5.0
   */
  columns: number;
  /**
   * Spatial domain rows.
   *
   * @since 5.0
   */
  rows: number;
  /**
   * Spatial domain x, y offset.
   *
   * @since 5.0
   */
  offset: {
      x: number;
      y: number;
  };
  /**
   * Spatial domain x, y origin.
   *
   * @since 5.0
   */
  origin: {
      x: number;
      y: number;
  };
}

/**
 * Temporal domain or extent of a coverage.
 *
 * @since 4.26
 */
export interface WCSTemporalDomain {
  /**
   * Start date for the temporal domain of a coverage.
   *
   * @since 5.0
   */
  begin: Date;
  /**
   * End date for the temporal domain of a coverage.
   *
   * @since 5.0
   */
  end: Date;
  /**
   * Date values available in the temporal domain.
   *
   * @since 5.0
   */
  values?: Date[] | null;
  /**
   * The numerical value of the temporal domain or extent.
   *
   * @since 5.0
   */
  resolution?: number | null;
  /**
   * Temporal units such as day, month, year etc.
   *
   * @since 5.0
   */
  units?: string | null;
}

/**
 * Coverage description for WCS service version 1.0.0.
 *
 * @since 4.26
 */
export interface WCSCoverageDescriptionV100 {
  /**
   * Coverage name.
   *
   * @since 5.0
   */
  name: string;
  /**
   * Coverage label.
   *
   * @since 5.0
   */
  label: string;
  /**
   * Coverage description.
   *
   * @since 5.0
   */
  description: string;
  /**
   * Formats supported by a coverage.
   *
   * @since 5.0
   */
  supportedFormats: string[];
  /**
   * Interpolations supported by a coverage.
   *
   * @since 5.0
   */
  supportedInterpolations: string[];
  /**
   * Coordinate reference systems supported by a coverage.
   *
   * @since 5.0
   */
  supportedCRSs: WCSCoverageDescriptionV100SupportedCRSs;
  /**
   * Spatial extent of the coverage.
   *
   * @since 5.0
   */
  lonLatEnvelope: Extent;
  /**
   * Defines the properties (categories, measures, or values) assigned to each location in the domain. It can numeric or text values, or
   * it can be a compound values such as income by race, or radiance by wave length. A compound range set may have more than one control parameter or set of “bins”, for
   * quantities related to values of several parameters (such as counts of wildlife tabulated both by size and by species).
   *
   * @since 5.0
   */
  rangeSet: WCSRangeSet[];
  /**
   * Describes the spatial and temporal domain of a coverage.
   *
   * @since 5.0
   */
  domainSet: WCSDomainSet;
  /**
   * Coverage version. It is always "1.0" for `CoverageDescriptionV100`.
   *
   * @since 5.0
   */
  readonly version: "1.0";
}

/** @since 5.0 */
export interface WCSCoverageDescriptionV100SupportedCRSs {
  /**
   * Coordinate reference systems in which the coverage can both accept GetCoverage requests and deliver coverage responses.
   *
   * @since 5.0
   */
  requestResponseCRSs: string[];
  /**
   * The native coordinate reference system of a coverage – that is, the coordinate reference systems in which coverages can be obtained without any distortion or degradation of the data.
   *
   * @since 5.0
   */
  nativeCRSs: string[];
}

/** @since 5.0 */
export interface WCSRangeSetV110 {
  /**
   * Range identifier.
   *
   * @since 5.0
   */
  identifier: string;
  /**
   * Range description.
   *
   * @since 5.0
   */
  description?: string | null;
  /**
   * Range definition.
   *
   * @since 5.0
   */
  definition: string;
  /**
   * Range abstract.
   *
   * @since 5.0
   */
  abstract?: string | null;
  /**
   * Range title.
   *
   * @since 5.0
   */
  title?: string | null;
  /**
   * Interpolations supported by the range.
   *
   * @since 5.0
   */
  supportedInterpolations: string[];
  /**
   * Null values.
   *
   * @since 5.0
   */
  nullValues: number[];
  /**
   * Statistics.
   *
   * @since 5.0
   */
  statistics?: RasterBandStatistics[] | null;
  /**
   * Provides additional information on compound valued range.
   *
   * @since 5.0
   */
  axis: WCSRangeSetV110Axis[];
}

/** @since 5.0 */
export interface WCSRangeSetV110Axis {
  /**
   * The range axis identifier.
   *
   * @since 5.0
   */
  identifier: string;
  /**
   * The axis unit of measurement.
   *
   * @since 5.0
   */
  uom: string;
  /**
   * The axis data type.
   *
   * @since 5.0
   */
  dataType: string;
  /**
   * The axis values.
   *
   * @since 5.0
   */
  values: string[];
  /**
   * The axis bandNoDataValues.
   *
   * @since 5.0
   */
  bandNoDataValues?: number[];
}

/** @since 5.0 */
export interface WCSSpatialDomainV110 extends WCSSpatialDomain {
  /**
   * Specifies spatial resolution of the coordinate reference system.
   *
   * @since 5.0
   */
  gridBaseCRS: string;
  /**
   * Indicates if the EPSG axis is used.
   *
   * @since 5.0
   */
  useEPSGAxis: boolean;
}

/** @since 5.0 */
export interface WCSDomainSetV110 {
  /**
   * Spatial extent or domain of a coverage.
   *
   * @since 5.0
   */
  spatialDomain: WCSSpatialDomainV110;
  /**
   * Temporal domain or extent of the coverage.
   *
   * @since 5.0
   */
  temporalDomain?: WCSTemporalDomain | null;
}

/**
 * Coverage description for WCS service version 1.1.0.
 *
 * @since 4.26
 */
export interface WCSCoverageDescriptionV110 {
  /**
   * Coverage title.
   *
   * @since 5.0
   */
  title: string;
  /**
   * Coverage abstract.
   *
   * @since 5.0
   */
  abstract: string;
  /**
   * Coverage identifier.
   *
   * @since 5.0
   */
  identifier: string;
  /**
   * Formats supported by a coverage.
   *
   * @since 5.0
   */
  supportedFormats: string[];
  /**
   * Coordinate reference systems supported by a coverage.
   *
   * @since 5.0
   */
  supportedCRSs: string[];
  /**
   * Describes the spatial and temporal domain of a coverage.
   *
   * @since 5.0
   */
  domain: WCSDomainSetV110;
  /**
   * Defines the properties (categories, measures, or values) assigned to each location in the domain. It can numeric or text values, or
   * it can be a compound values such as income by race, or radiance by wave length. A compound range set may have more than one control parameter or set of “bins”, for
   * quantities related to values of several parameters (such as counts of wildlife tabulated both by size and by species).
   *
   * @since 5.0
   */
  range: WCSRangeSetV110[];
  /**
   * Resolution x, y.
   *
   * @since 5.0
   */
  resolution: PixelSize;
  /**
   * Coverage metadata.
   *
   * @since 5.0
   */
  metadata?: string;
  /**
   * Coverage version. It is always "1.1" for `CoverageDescriptionV110`.
   *
   * @since 5.0
   */
  readonly version: "1.1";
}

/** @since 5.0 */
export interface WCSBoundedByV201 {
  /**
   * The spatial extent of a coverage.
   *
   * @since 5.0
   */
  envelope: Extent;
  /**
   * The coverage's axis name.
   *
   * @since 5.0
   */
  axisLabels: string[];
  /**
   * List of unit of measure (uom) labels for all the axis.
   *
   * @since 5.0
   */
  uomLabels?: string[] | null;
  /**
   * The spatial extent dimensions.
   *
   * @since 5.0
   */
  envelopeAllDims: WCSBoundedByV201EnvelopeAllDims;
  /**
   * Start date for the temporal extent of a coverage.
   *
   * @since 5.0
   */
  beginPosition?: Date | null;
  /**
   * End date for the temporal extent of the coverage.
   *
   * @since 5.0
   */
  endPosition?: Date | null;
  /**
   * Is east first.
   *
   * @since 5.0
   */
  isEastFirst: boolean;
}

/** @since 5.0 */
export interface WCSBoundedByV201EnvelopeAllDims {
  /**
   * Spatial extent min x and y.
   *
   * @since 5.0
   */
  mins: number[];
  /**
   * Spatial extent min x and y.
   *
   * @since 5.0
   */
  maxs: number[];
}

/** @since 5.0 */
export interface WCSRangeFieldV201 {
  /**
   * Range type name.
   *
   * @since 5.0
   */
  name: string;
  /**
   * Range type description.
   *
   * @since 5.0
   */
  description?: string | null;
  /**
   * Unit of measurement for the range type.
   *
   * @since 5.0
   */
  uom: string;
  /**
   * Number that represents null value.
   *
   * @since 5.0
   */
  nilValue?: number | null;
  /**
   * Allowed values for the range type.
   *
   * @since 5.0
   */
  allowedValues?: number[] | null;
}

/** @since 5.0 */
export interface WCSDomainSetV201 {
  /**
   * Domain columns of a coverage.
   *
   * @since 5.0
   */
  columns: number;
  /**
   * Domain rows of a coverage.
   *
   * @since 5.0
   */
  rows: number;
  /**
   * Domain origin.
   *
   * @since 5.0
   */
  origin: number[];
  /**
   * Domain offset.
   *
   * @since 5.0
   */
  offset: number[];
  /**
   * Domain x, y resolution.
   *
   * @since 5.0
   */
  resolution: PixelSize;
  /**
   * Domain grid samples.
   *
   * @since 5.0
   */
  gridSamples: number[];
  /**
   * Axis labels.
   *
   * @since 5.0
   */
  axisLabels: string[];
  /**
   * Has same axis labels as bounded by.
   *
   * @since 5.0
   */
  hasSameAxisLabelsAsBoundedBy: boolean;
}

/** @since 5.0 */
export interface WCSEOCoverageMetadata {
  /**
   * Earth observation.
   *
   * @since 5.0
   */
  observation: WCSEOCoverageMetadataObservation;
}

/** @since 5.0 */
export interface WCSEOCoverageMetadataObservation {
  /**
   * Earth observation phenomenon time.
   *
   * @since 5.0
   */
  phenomenonTime?: WCSTemporalDomain | null;
  /**
   * Earth observation resultTime.
   *
   * @since 5.0
   */
  resultTime?: WCSTemporalDomain | null;
  /**
   * Earth observation footprint.
   *
   * @since 5.0
   */
  footprint?: Polygon | null;
  /**
   * Earth observation identifier.
   *
   * @since 5.0
   */
  identifier: string;
  /**
   * Earth observation acquisition type.
   *
   * @since 5.0
   */
  acquisitionType?: string | null;
  /**
   * Earth observation status.
   *
   * @since 5.0
   */
  status?: string | null;
}

/**
 * Coverage description for WCS service version 2.0.1
 *
 * @since 4.26
 */
export interface WCSCoverageDescriptionV201 {
  /**
   * Coverage id.
   *
   * @since 5.0
   */
  coverageId: string;
  /**
   * Spatial and temporal extent of a coverage.
   *
   * @since 5.0
   */
  boundedBy: WCSBoundedByV201;
  /**
   * Domains associated with a coverage.
   *
   * @since 5.0
   */
  domainSet: WCSDomainSetV201;
  /**
   * Describes the semantics of the range set values supported by a coverage.
   *
   * @since 5.0
   */
  rangeType: WCSRangeFieldV201[][];
  /**
   * Service parameters.
   *
   * @since 5.0
   */
  serviceParameters: Record<string, any>;
  /**
   * Service x,y resolution.
   *
   * @since 5.0
   */
  resolution: PixelSize;
  /**
   * Coverage function.
   *
   * @since 5.0
   */
  coverageFunction?: any | null;
  /**
   * Coverage extension.
   *
   * @since 5.0
   */
  extension?: string | null;
  /**
   * The WCS 2.0 Earth Observation coverage metadata.
   *
   * @since 5.0
   */
  eoMetadata?: WCSEOCoverageMetadata | null;
  /**
   * Service version.
   *
   * @since 5.0
   */
  readonly version: "2.0";
}