import type SimpleBandStatistics from "./SimpleBandStatistics.js";
import type { JSONSupport, JSONSupportMixinProperties } from "../../core/JSONSupport.js";
import type { RasterNumArray, RasterPixelType } from "./RasterTypes.js";

export interface PixelBlockProperties extends JSONSupportMixinProperties, Partial<Pick<PixelBlock, "bandMasks" | "height" | "mask" | "maskIsAlpha" | "pixels" | "pixelType" | "statistics" | "validPixelCount" | "width">> {}

/**
 * An object representing the pixel arrays in the view. It stores and decodes source data
 * fetched from an image service associated with an [ImageryLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html). This provides the
 * user access to each pixel on the client via the [pixels](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-PixelBlock.html#pixels) property.
 * The PixelBlock object is designed to handle generic pixel arrays from any raster data source.
 *
 * @since 4.0
 * @see [ImageryLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-ImageryLayer.html)
 * @see [Sample - Access pixel values in an ImageryLayer](https://developers.arcgis.com/javascript/latest/sample-code/layers-imagery-pixelvalues/)
 */
export default class PixelBlock extends JSONSupport {
  constructor(properties?: PixelBlockProperties);
  /** Masks for each band. 0 means noData. */
  accessor bandMasks: Uint8Array<ArrayBuffer>[] | null | undefined;
  /** The height (or number of rows) of the PixelBlock in pixels. */
  accessor height: number;
  /** An array of nodata mask. All pixels are valid when mask is null. */
  accessor mask: Uint8Array<ArrayBuffer> | null | undefined;
  /**
   * Indicates whether mask should be used as alpha values. If no (default), a pixel is valid when corresponding mask value is truthy
   *
   * @default false
   */
  accessor maskIsAlpha: boolean;
  /**
   * A two dimensional array representing the pixels from the Image Service
   * displayed on the client. The length of the first dimension is the same as
   * the number of bands in the layer. The length of the second dimension is
   * [height](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-PixelBlock.html#height) * [width](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-PixelBlock.html#width). The length of each band is the same. The
   * pixels in each band are arranged row by row in this format:
   * `[p_00, p_10, p_20, ... p_10, p_11, ...]` where `p_xy` is the pixel value
   * at the column `x` and row `y`.
   *
   * @example
   * let pixels = imgLyr.pixelData.pixelBlock.pixels;
   * // Prints the number of bands in the layer
   * console.log(pixels.length);
   * // An array containing all the pixels in the first band
   * let band1 = pixels[0];
   */
  accessor pixels: RasterNumArray[];
  /**
   * The pixel type.
   *
   * @default "f32"
   */
  accessor pixelType: RasterPixelType;
  /**
   * An array of objects containing numeric statistical properties. Each object
   * has the following specification if defined.
   */
  accessor statistics: SimpleBandStatistics[] | null | undefined;
  /** Number of valid pixels */
  accessor validPixelCount: number | null | undefined;
  /** The width (or number of columns) of the PixelBlock in pixels. */
  accessor width: number;
  /**
   * Adds another plane to the PixelBlock.
   *
   * @param planeData - The data to add to the PixelBlock.
   */
  addData(planeData: PixelBlockPlaneData): void;
  /**
   * Returns pixels and masks using a single array in bip format
   * (e.g. [p_00_r, p_00_g, p_00_b, p_00_a, p_10_r, p_10_g, p_10_b, p_10_a, .....]).
   * Use this method to get an unsigned 8 bit pixel array.
   * The result can be used to create a webgl texture.
   *
   * @returns An unsigned 8-bit pixel array.
   */
  getAsRGBA(): Uint8ClampedArray<ArrayBuffer>;
  /**
   * Similar to [getAsRGBA()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-PixelBlock.html#getAsRGBA), but returns floating point data.
   * The result can be used to create a webgl texture (OES_texture_float).
   *
   * @returns A floating point array.
   */
  getAsRGBAFloat(): Float32Array<ArrayBuffer>;
  /**
   * Returns the plane band count of the PixelBlock.
   *
   * @returns The plane band count.
   */
  getPlaneCount(): number | null | undefined;
}

export interface PixelBlockPlaneData {
  /** An array representing the pixel data to add. */
  pixels: number[];
  /** An object containing numeric statistical properties. */
  statistics?: SimpleBandStatistics;
}