import type Point from "../../geometry/Point.js";
import type DimensionalDefinition from "./DimensionalDefinition.js";
import type RasterFunction from "./RasterFunction.js";
import type { JSONSupport, JSONSupportMixinProperties } from "../../core/JSONSupport.js";
import type { RasterFunctionProperties } from "./RasterFunction.js";
import type { DimensionalDefinitionProperties } from "./DimensionalDefinition.js";
import type { PointProperties } from "../../geometry/Point.js";

export interface MosaicRuleProperties extends JSONSupportMixinProperties, Partial<Pick<MosaicRule, "ascending" | "lockRasterIds" | "method" | "objectIds" | "operation" | "sortField" | "sortValue" | "where">> {
  /**
   * The raster function applied on items before mosaicking.
   *
   * @since 4.27
   */
  itemRasterFunction?: RasterFunctionProperties | null;
  /**
   * The multidimensional definitions associated with the [ImageryLayer#mosaicRule](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html#mosaicRule).
   * Filters the layer by slicing data along defined variables and dimensions such as
   * time, depth, altitude, etc. For example, you can display a particular variable such as temperature or salinity measured at a fixed dimension
   * (e.g. time, depth). These data types are commonly used in atmospheric, oceanographic, and earth sciences.
   * For example, it can be used to display sea temperature at -1000m below sea level for a specific week in the year.
   *
   * Multiple definitions are consolidated by server into one single where clause. The consolidation rule is:
   * * For the same variableName but different dimensionName, it uses the `AND` operator to connect all dimension conditions for the same variable.
   * * For different variableName, it uses the `OR` operator to connect any variable that meets the dimension conditions.
   *
   * @see [ImageryLayer - working with multidimensional raster data](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html#multidimensionaldata)
   * @see [Sample - Work with pixelFilter in an ImageryLayer](https://developers.arcgis.com/javascript/latest/sample-code/layers-imagery-pixelvalues/)
   * @example
   * // Display water salinity at a specific point in time.
   * // In this case - Nov 30 2009
   * let mosaicRule = new MosaicRule();
   * mosaicRule.multidimensionalDefinition = [];
   * mosaicRule.multidimensionalDefinition.push(new DimensionalDefinition({
   *   variableName: "Salinity",
   *   dimensionName: "StdTime",
   *   values: [1259625600000]
   * }));
   *
   * layer.mosaicRule = mosaicRule;
   */
  multidimensionalDefinition?: DimensionalDefinitionProperties[] | null;
  /**
   * Defines the viewpoint location on which the ordering is defined based on the
   * distance from the viewpoint and the nadir of rasters.
   *
   * @example
   * let mosaicRule = new MosaicRule();
   * mosaicRule.method = "viewpoint";
   * mosaicRule.viewpoint = inPoint;
   * layer.mosaicRule = mosaicRule;
   */
  viewpoint?: PointProperties | null;
}

export type OperationType = "first" | "last" | "min" | "max" | "mean" | "blend" | "sum";

export type MethodType = "none" | "center" | "nadir" | "viewpoint" | "attribute" | "lock-raster" | "northwest" | "seamline";

/**
 * Specifies the mosaic rule when defining how individual images should be mosaicked.
 * It specifies selection, mosaic method, sort order, overlapping pixel resolution, etc.
 * Mosaic rules are for mosaicking rasters in the mosaic dataset. A mosaic rule is used to define:
 *
 * * The selection of rasters that will participate in the mosaic (using where clause).
 * * The mosaic method, e.g. how the selected rasters are ordered.
 * * The mosaic operation, e.g. how overlapping pixels at the same location are resolved.
 *
 * @since 4.0
 * @see [Sample - Work with pixelFilter in an ImageryLayer](https://developers.arcgis.com/javascript/latest/sample-code/layers-imagery-pixelvalues/)
 * @see [Sample - ImageryLayer raster function](https://developers.arcgis.com/javascript/latest/sample-code/layers-imagery-rasterfunction/)
 * @see [Mosaicking rules for a mosaic dataset](https://pro.arcgis.com/en/pro-app/latest/help/data/imagery/mosaicking-rules-for-a-mosaic-dataset-pro-.htm)
 * @example
 * new MosaicRule({
 *   ascending: true,
 *   method: "center",
 *   operation: "last"
 * });
 */
export default class MosaicRule extends JSONSupport {
  constructor(properties?: MosaicRuleProperties);
  /**
   * Indicates whether the sort should be ascending. This property applies to all mosaic
   * [methods](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-MosaicRule.html#method) where an ordering is defined except `seamline`.
   *
   * @default true
   */
  accessor ascending: boolean;
  /**
   * The raster function applied on items before mosaicking.
   *
   * @since 4.27
   */
  get itemRasterFunction(): RasterFunction | null | undefined;
  set itemRasterFunction(value: RasterFunctionProperties | null | undefined);
  /**
   * An array of raster Ids. All the rasters with the given list of raster Ids are
   * selected to participate in the mosaic. The rasters will be visible at all pixel
   * sizes regardless of the minimum and maximum pixel size range of the locked rasters.
   *
   * @example
   * let mosaicRule = new MosaicRule();
   * mosaicRule.method = "lock-raster";
   * mosaicRule.lockRasterIds = [32,454,14];
   */
  accessor lockRasterIds: number[] | null | undefined;
  /**
   * The mosaic method determines how the selected rasters are ordered.
   * The mosaic method defines how the mosaicked image is created from these input rasters.
   *
   * Value | Description |
   * ----- | ----------- |
   * none | Orders rasters based on the order of [objectIds](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-MosaicRule.html#objectIds) in the mosaic dataset attribute table.
   * center | Enables rasters to be sorted based their ZOrder, then PixelSize, and then by a default order where rasters that have their centers closest to the view center are placed on top.
   * nadir | Enables rasters to be sorted by the ZOrder, then PixelSize, and then by the distance between the nadir position and view center. This is similar to the Closest to Center method but uses the nadir point to a raster, which may be different than the center, especially for oblique imagery.
   * viewpoint | Orders rasters based on the ZOrder, then PixelSize, and then by a user-defined location and nadir location for the rasters using the [viewpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-MosaicRule.html#viewpoint).
   * attribute | Enables raster ordering based on ZOrder, then PixelSize, and then by a defined metadata attribute and its difference from a base value.
   * lock-raster | Enables a user to lock the display of single or multiple rasters based on the [lockRasterIds](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-MosaicRule.html#lockRasterIds).
   * northwest | Enables raster ordering by ZOrder, then PixelSize, and then by the shortest distance between the center of a raster to the northwest position.
   * seamline| Cuts the raster using the predefined seamline shape for each raster, using optional feathering along the seams, and orders images based on the ZOrder and then the SOrder fields in the attribute table.
   *
   * @default "none"
   * @example
   * let mosaicRule = new MosaicRule();
   * mosaicRule.method = "lock-raster";
   */
  accessor method: MethodType;
  /**
   * The multidimensional definitions associated with the [ImageryLayer#mosaicRule](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html#mosaicRule).
   * Filters the layer by slicing data along defined variables and dimensions such as
   * time, depth, altitude, etc. For example, you can display a particular variable such as temperature or salinity measured at a fixed dimension
   * (e.g. time, depth). These data types are commonly used in atmospheric, oceanographic, and earth sciences.
   * For example, it can be used to display sea temperature at -1000m below sea level for a specific week in the year.
   *
   * Multiple definitions are consolidated by server into one single where clause. The consolidation rule is:
   * * For the same variableName but different dimensionName, it uses the `AND` operator to connect all dimension conditions for the same variable.
   * * For different variableName, it uses the `OR` operator to connect any variable that meets the dimension conditions.
   *
   * @see [ImageryLayer - working with multidimensional raster data](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html#multidimensionaldata)
   * @see [Sample - Work with pixelFilter in an ImageryLayer](https://developers.arcgis.com/javascript/latest/sample-code/layers-imagery-pixelvalues/)
   * @example
   * // Display water salinity at a specific point in time.
   * // In this case - Nov 30 2009
   * let mosaicRule = new MosaicRule();
   * mosaicRule.multidimensionalDefinition = [];
   * mosaicRule.multidimensionalDefinition.push(new DimensionalDefinition({
   *   variableName: "Salinity",
   *   dimensionName: "StdTime",
   *   values: [1259625600000]
   * }));
   *
   * layer.mosaicRule = mosaicRule;
   */
  get multidimensionalDefinition(): DimensionalDefinition[] | null | undefined;
  set multidimensionalDefinition(value: DimensionalDefinitionProperties[] | null | undefined);
  /** Defines a selection using a set of ObjectIDs. This property applies to all mosaic methods. */
  accessor objectIds: number[] | null | undefined;
  /**
   * Defines the mosaic operation used to resolve overlapping pixels.
   *
   * **Possible Values**
   *
   * Value | Description |
   * ----- | ----------- |
   * first | The overlapping areas will contain the cells from the first raster dataset listed in the source.
   * last | The overlapping areas will contain the cells from the last raster dataset listed in the source.
   * min | The overlapping areas will contain the minimum cell values from all the overlapping cells.
   * max | The overlapping areas will contain the maximum cell values from all the overlapping cells.
   * mean | The overlapping areas will contain the mean cell values from all the overlapping cells.
   * blend | The overlapping areas will be a blend of the cell values that overlap. This blend value relies on an algorithm that is weight based and dependent on the distance from the cells to the edge within the overlapping area.
   * sum | The overlapping areas will contain the total sum of the cell values from all the overlapping cells.
   *
   * @default "first"
   */
  accessor operation: OperationType;
  /**
   * The name of the attribute field that is used with a constant sortValue to define the mosaicking
   * order when the mosaic [method](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-MosaicRule.html#method) is set to `attribute`. The ordering is defined
   * by the absolute value of the difference between the specified sort field value and the sort base
   * value. For example, if the sort field is `Month` and the sort value is `7 (July)`, then the ordering
   * is defined by `ABS(Month -7)`.
   */
  accessor sortField: string | null | undefined;
  /**
   * A constant value defining a reference or base value for the sort field when the mosaic [method](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-MosaicRule.html#method)
   * is set to `attribute`.
   */
  accessor sortValue: string | number;
  /**
   * Defines the viewpoint location on which the ordering is defined based on the
   * distance from the viewpoint and the nadir of rasters.
   *
   * @example
   * let mosaicRule = new MosaicRule();
   * mosaicRule.method = "viewpoint";
   * mosaicRule.viewpoint = inPoint;
   * layer.mosaicRule = mosaicRule;
   */
  get viewpoint(): Point | null | undefined;
  set viewpoint(value: PointProperties | null | undefined);
  /**
   * The where clause determines which rasters will participate in the mosaic.
   * This property applies to all mosaic methods. This property will be overridden
   * by the ImageryLayer's [ImageryLayer#definitionExpression](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html#definitionExpression)
   * property if both properties are set.
   */
  accessor where: string | null | undefined;
  /**
   * Creates a clone of the MosaicRule object.
   *
   * @returns A clone of the object that invoked this method.
   * @example
   * // Creates a clone of the mosaic rule
   * let mosaicRule = layer.mosaicRule.clone();
   */
  clone(): MosaicRule;
}