import type { ToolStateManager } from '@dcm/cornerstone-tools';

/** Number range array */
export type Range = [lower: number, upper: number];
/** 3-channel format color containing data for Red, Green, and Blue */
export type RGB = [green: number, red: number, blue: number];
/** 4-channel format color containing data for Red, Green, Blue, and Alpha */
export type RGBA = [green: number, red: number, blue: number, alpha: number];
/** A string value representing the shape of the table */
export type RampShape = 'linear' | 'scurve' | 'sqrt';
/** The schemes supportted by image loaders */
export type ImageLoaderSchema = 'dicomweb' | 'wadors' | 'wadouri' | 'dicomfile' | 'http' | 'https';
/** Supportted pixel data types */
export type PixelData = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array;
/** Presentation size mode */
export type PresentationSizeMode = 'NONE' | 'TRUE SIZE' | 'SCALE TO FIT' | 'MAGNIFY';
/** Grayscale LUT  */
export type GrayscaleLUT = number[];
/** Color LUT  */
export type ColorLUT = (RGB | RGBA)[];
/** Grayscale or color LUT */
export type LUT = GrayscaleLUT | ColorLUT;
/** Metadata provider function */
export type MetadataProvider = (type: string, imageId: string) => any;
/** A two-dimensional vector */
export interface Vec2 {
  x: number;
  y: number;
}
/** The value of interest */
export interface VOI {
  windowWidth: number;
  windowCenter: number;
}

/**
 * Maps scalar values into colors via a lookup table
 *
 * LookupTable is an object that is used by mapper objects to map scalar values into rgba (red-green-blue-alpha transparency) color specification,
 * or rgba into scalar values. The color table can be created by direct insertion of color values, or by specifying hue, saturation, value, and alpha range and generating a table
 */
export interface LookupTable {
  NumberOfColors: number;
  Ramp: RampShape;
  TableRange: Range;
  HueRange: Range;
  SaturationRange: Range;
  ValueRange: Range;
  AlphaRange: Range;
  NaNColor: RGBA;
  BelowRangeColor: RGBA;
  UseBelowRangeColor: boolean;
  AboveRangeColor: RGBA;
  UseAboveRangeColor: boolean;
  InputRange: Range;
  Table: RGBA[];
  new (): LookupTable;
  setNumberOfTableValues(number: number): void;
  setRamp(ramp: RampShape): void;
  setTableRange(start: number, end: number): void;
  setHueRange(start: number, end: number): void;
  setSaturationRange(start: number, end: number): void;
  setValueRange(start: number, end: number): void;
  setRange(start: number, end: number): void;
  setAlphaRange(start: number, end: number): void;
  getColor(scalar: number): RGBA;
  build(force: boolean): void;
  buildSpecialColors(): void;
  mapValue(value: number): RGBA;
  getIndex(value: number): number;
  setTableValue(index: number, rgba: RGBA): void;
}

/** Simple class for keeping track of the current transformation matrix */
export interface Transform {
  m: [
    scaleX: number,
    skewY: number,
    skewX: number,
    scaleY: number,
    translateX: number,
    translateY: number,
  ];
  new (): Transform;
  reset(): void;
  clone(): Transform;
  multiply(matrix: Transform): void;
  invert(): void;
  rotate(rad: number): void;
  translate(x: number, y: number): void;
  scale(sx: number, sy: number): void;
  transformPoint(px: number, py: number): Vec2;
}

/** Modality LUT */
export interface ModalityLUT {
  id: string;
  firstValueMapped: number;
  numBitsPerEntry: number;
  lut: LUT;
}

/** VOI LUT */
export interface VOILUT {
  id: string;
  firstValueMapped: number;
  numBitsPerEntry: number;
  lut: LUT;
}

/** Colormap data object */
export interface ColormapData {
  name: string;
  numOfColors: number;
  gamma?: number;
  colors?: RGBA[];
  segmentedData?: {
    red: RGB[];
    green: RGB[];
    blue: RGB[];
  };
}

/**
 * Supportted colormaps of cornerstone
 *
 * Hot Iron, PET, Hot Metal Blue and PET 20 Step are color palettes defined by the DICOM standard
 * http://dicom.nema.org/dicom/2013/output/chtml/part06/chapter_B.html
 *
 * All Linear Segmented Colormaps were copied from matplotlib
 * https://github.com/stefanv/matplotlib/blob/master/lib/matplotlib/_cm.py
 *
 */
export interface ColormapDataMap {
  hotIron: ColormapData;
  pet: ColormapData;
  hotMetalBlue: ColormapData;
  pet20Step: ColormapData;
  gray: ColormapData;
  jet: ColormapData;
  hsv: ColormapData;
  hot: ColormapData;
  cool: ColormapData;
  spring: ColormapData;
  summer: ColormapData;
  autumn: ColormapData;
  winter: ColormapData;
  bone: ColormapData;
  copper: ColormapData;
  spectral: ColormapData;
  coolwarm: ColormapData;
  blues: ColormapData;
}

/** Supportted colormap IDs of cornerstone */
export type ColormapID = keyof ColormapDataMap;

/** Colormap object with id and name */
export interface Colormap {
  id: ColormapID;
  name: string;
}

/** Colormap object */
export interface ColormapObject {
  getId(): string;
  getColorSchemeName(): string;
  setColorSchemeName(name: string): void;
  getNumberOfColors(): number;
  setNumberOfColors(numColors: number): void;
  getColor(index: number): RGBA;
  getColorRepeating(index: number): number;
  setColor(index: number, rgba: RGBA): void;
  addColor(rgba: RGBA): void;
  insertColor(index: number, rgba: RGBA): void;
  removeColor(index: number): void;
  clearColors(): void;
  buildLookupTable(lut?: LookupTable): void;
  createLookupTable(): LookupTable;
  isValidIndex(index: number): boolean;
}

/** Image statistics object */
export interface ImageStats {
  lastGetPixelDataTime?: number;
  lastStoredPixelDataToCanvasImageDataTime?: number;
  lastPutImageDataTime?: number;
  lastRenderTime?: number;
  lastLutGenerateTime?: number;
}

/** Cornerstone image object */
export interface Image {
  /** The imageId associated with this image object */
  imageId: string;
  /** The minimum stored pixel value in the image */
  minPixelValue: number;
  /** The maximum stored pixel value in the image */
  maxPixelValue: number;
  /** The rescale slope to convert stored pixel values to modality pixel values or 1 if not specified */
  slope: number;
  /** The rescale intercept used to convert stored pixel values to modality values or 0 if not specified  */
  intercept: number;
  /** The default windowCenter to apply to the image */
  windowCenter: number;
  /** The default windowWidth to apply to the image */
  windowWidth: number;
  /** A function that returns the underlying pixel data. An array of integers for grayscale and an array of RGBA for color */
  getPixelData: () => PixelData;
  /** A function that returns a canvas imageData object for the image. This is only needed for color images */
  getImageData?: () => ImageData;
  /** A function that returns a canvas element with the image loaded into it. This is only needed for color images */
  getCanvas?: () => HTMLCanvasElement;
  /** A function that returns a JavaScript Image object with the image data. This is optional and typically used for images encoded in standard web JPEG and PNG formats */
  getImage?: () => HTMLImageElement;
  /** Number of rows in the image. This is the same as height but duplicated for convenience */
  rows: number;
  /** Number of columns in the image. This is the same as width but duplicated for convenience */
  columns: number;
  /** The height of the image. This is the same as rows but duplicated for convenience */
  height: number;
  /** The width of the image. This is the same as columns but duplicated for convenience */
  width: number;
  /** True if pixel data is RGB, false if grayscale */
  color: boolean;
  /** The Lookup Table */
  lut?: LookupTable;
  /** Is the color pixel data stored in RGBA? */
  rgba?: boolean;
  /** Horizontal distance between the middle of each pixel (or width of each pixel) in mm or undefined if not known */
  columnPixelSpacing?: number;
  /** Vertical distance between the middle of each pixel (or height of each pixel) in mm or undefined if not known */
  rowPixelSpacing?: number;
  /** True if the the image should initially be displayed be inverted, false if not. This is here mainly to support DICOM images with a photometric interpretation of MONOCHROME1 */
  invert: boolean;
  /** The number of bytes used to store the pixels for this image */
  sizeInBytes: number;
  /** Whether or not the image has undergone false color mapping */
  falseColor?: boolean;
  /** Original pixel data for an image after it has undergone false color mapping */
  origPixelData?: PixelData;
  /** Statistics for the last redraw of the image */
  stats?: ImageStats;
  /** Cached Lookup Table for this image */
  cachedLut: {
    invert: boolean;
    lutArray: Uint8ClampedArray;
    modalityLUT?: ModalityLUT;
    voiLUT?: VOILUT;
    windowCenter: number;
    windowWidth: number;
  };
  /**
   * Use viewport.colormap instead. an optional colormap ID or colormap object (from colors/colormap.js).
   *
   * @deprecated
   */
  colormap?: ColormapID | ColormapObject;
  /** Whether or not to render this image as a label map (i.e. skip modality and VOI LUT pipelines and use only a color lookup table) */
  labelmap?: boolean;
  /** Load time in millisecond */
  loadTimeInMS: number;
  /** Decode time in millisecond */
  decodeTimeInMS: number;
  /** Float pixel data */
  floatPixelData?: PixelData;
}

/** Enabled element viewport state */
export interface Viewport {
  scale: number;
  translation: Vec2;
  voi: Partial<VOI>;
  invert: boolean;
  pixelReplication: boolean;
  rotation: number;
  hflip: boolean;
  vflip: boolean;
  modalityLUT?: ModalityLUT;
  voiLUT?: VOILUT;
  colormap?: ColormapID | ColormapObject;
  labelmap: boolean;
  displayedArea: DisplayedArea;
}

/** Image load object */
export interface ImageLoadObject {
  promise: Promise<Image>;
  cancelFn?: () => void;
}

/** Image loader options */
export interface ImageLoaderOptions extends Record<string, any> {}

/** Image texture object */
export interface ImageTexture extends Record<string, any> {
  sizeInBytes: number;
}

/** Cached image object */
export interface CachedImage {
  loaded?: boolean;
  imageId: string;
  sharedCacheKey?: string;
  imageLoadObject?: ImageLoadObject;
  imageTexture?: ImageTexture;
  timeStamp: number;
  sizeInBytes: number;
}

/** Image cache dictionary */
export type ImageCacheDict = Record<string, CachedImage>;

/** Current information of image cache */
export interface CacheInformation {
  maximumSizeInBytes: number;
  cacheSizeInBytes: number;
  numberOfImagesCached: number;
}

/** Enable elment options  */
export interface EnableElementOptions extends Record<string, any> {
  renderer?: 'webgl';
}

/** Enabled elment layer object */
export interface EnabledElementLayer {
  /** The DOM element which has been enabled for use by Cornerstone */
  element: HTMLElement;
  /** The image currently displayed in the enabledElement */
  image?: Image;
  /** The current viewport settings of the enabledElement */
  viewport?: Viewport;
  /** The current canvas for this enabledElement */
  canvas?: HTMLCanvasElement;
  /** Layer drawing options */
  options?: {
    /** Opacity settings that have been defined for this layer */
    opacity?: number;
    /** Colormap settings that have been defined for this layer */
    colormap?: Colormap | ColormapID;
  };
  /** Whether or not the image pixel data underlying the enabledElement has been changed, necessitating a redraw */
  invalid: boolean;
  /** A flag for triggering a redraw of the canvas without re-retrieving the pixel data, since it remains valid */
  needsRedraw: boolean;
}

/** Enabled element object */
export interface EnabledElement {
  uuid: string;
  /** The DOM element which has been enabled for use by Cornerstone */
  element: HTMLElement;
  /** The image currently displayed in the enabledElement */
  image?: Image;
  /** The current viewport settings of the enabledElement */
  viewport?: Vwport;
  /** The current canvas for this enabledElement */
  canvas?: HTMLCanvasElement;
  /** Whether or not the image pixel data underlying the enabledElement has been changed, necessitating a redraw */
  invalid: boolean;
  /** A flag for triggering a redraw of the canvas without re-retrieving the pixel data, since it remains valid */
  needsRedraw: boolean;
  /** The layers that have been added to the enabledElement */
  layers?: EnabledElementLayer[];
  /** Whether or not to synchronize the viewport parameters for each of the enabled element's layers */
  syncViewports?: boolean;
  /**  The previous state for the sync viewport boolean */
  lastSyncViewportsState?: boolean;
  /** Options of enabled element */
  options?: EnableElementOptions;
  /** Data of enabled element */
  data: Record<string, any>;
  /** Rendering Tools */
  renderingTools: {
    renderCanvas: HTMLCanvasElement;
    renderCanvasContext: CanvasRenderingContext2D;
    renderCanvasData: ImageData;
    lastRenderedImageId?: string;
    lastRenderedIsColor?: boolean;
    lastRenderedViewport?: Partial<Viewport>;
  };
  /** Toolstate manager */
  toolStateManager?: ToolStateManager;
  /** Last image tiemstamp */
  lastImageTimeStamp: number;
}

/** Displayed area object */
export interface DisplayedArea {
  tlhc: Vec2;
  brhc: Vec2;
  rowPixelSpacing: number;
  columnPixelSpacing: number;
  presentationSizeMode: PresentationSizeMode;
}

/**
 * Load an image using a registered Cornerstone Image Loader.
 *
 * @param {string} imageId A Cornerstone Image Object's imageId
 * @param {ImageLoaderOptions} [options] Options to be passed to the Image Loader
 * @returns {ImageLoadObject} An Object which can be used to act after an image is loaded or loading fails
 */
export type ImageLoader = (imageId: string, options?: ImageLoaderOptions) => ImageLoadObject;

/** Supportted events by cornerstone */
export type CornerstoneEvents = Cornerstone['EVENTS'];

/** Cornerstone event key */
export type CornerstoneEventKey = keyof CornerstoneEvents;

/** Cornerstone event value */
export type CornerstoneEventValue = CornerstoneEvents[CornerstoneEventKey];

/* -------------------- Cornerstone -------------------- */

export interface Cornerstone {
  /** Supportted events of cornerstone */
  EVENTS: {
    ACTIVE_LAYER_CHANGED: 'cornerstoneactivelayerchanged';
    ELEMENT_DISABLED: 'cornerstoneelementdisabled';
    ELEMENT_ENABLED: 'cornerstoneelementenabled';
    ELEMENT_RESIZED: 'cornerstoneelementresized';
    IMAGE_CACHE_CHANGED: 'cornerstoneimagecachechanged';
    IMAGE_CACHE_FULL: 'cornerstoneimagecachefull';
    IMAGE_CACHE_MAXIMUM_SIZE_CHANGED: 'cornerstoneimagecachemaximumsizechanged';
    IMAGE_CACHE_PROMISE_REMOVED: 'cornerstoneimagecachepromiseremoved';
    IMAGE_LOADED: 'cornerstoneimageloaded';
    IMAGE_LOAD_FAILED: 'cornerstoneimageloadfailed';
    IMAGE_RENDERED: 'cornerstoneimagerendered';
    INVALIDATED: 'cornerstoneinvalidated';
    LAYER_ADDED: 'cornerstonelayeradded';
    LAYER_REMOVED: 'cornerstonelayerremoved';
    NEW_IMAGE: 'cornerstonenewimage';
    PRE_RENDER: 'cornerstoneprerender';
    WEBGL_TEXTURE_CACHE_FULL: 'cornerstonewebgltexturecachefull';
    WEBGL_TEXTURE_REMOVED: 'cornerstonewebgltextureremoved';
  };

  /**
   * Adds a Cornerstone Enabled Element object to the central store of enabledElements
   *
   * @param {EnabledElement} enabledElement A Cornerstone enabledElement Object
   * @returns {void}
   */
  addEnabledElement(enabledElement: EnabledElement): void;

  /**
   * Add a layer to a Cornerstone element
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {Image} [image] A Cornerstone Image object to add as a new layer
   * @param {Record<string, any>} [options] Options for the layer
   * @returns {string} layerId The new layer's unique identifier
   */
  addLayer(element: HTMLElement, image?: Image, options?: Record<string, any>): string;

  /**
   * Converts a point in the canvas coordinate system to the pixel coordinate system
   * system.  This can be used to reset tools' image coordinates after modifications
   * have been made in canvas space (e.g. moving a tool by a few cm, independent of
   * image resolution).
   *
   * @param {HTMLElement} element The Cornerstone element within which the input point lies
   * @param {Vec2} point The input point in the canvas coordinate system
   * @returns {Vec2} The transformed point in the pixel coordinate system
   */
  canvasToPixel(element: HTMLElement, point: Vec2): Vec2;

  colors: {
    /** Lookup table */
    LookupTable: LookupTable;

    /**
     * Return a colorMap object with the provided id and colormapData
     * if the Id matches existent colorMap objects (check colormapsData) the colormapData is ignored.
     * if the colormapData is not empty, the colorMap will be added to the colormapsData list. Otherwise, an empty colorMap object is returned.
     *
     * @param {ColormapID} id The ID of the colormap
     * @param {ColormapData} [colormapData] An object that can contain a name, numColors, gama, segmentedData and/or colors
     * @returns {ColormapObject} The Colormap Object
     */
    getColormap(id: ColormapID, colormapData?: ColormapData): ColormapObject;

    /**
     * Return all available colormaps (id and name)
     *
     * @returns {Colormap[]} An array of colormaps
     */
    getColormapsList(): Colormap[];
  };

  /**
   * Convert an image to a false color image
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {ColormapID | ColormapObject} colormap It can be a colormap object or a colormap ID
   * @returns {boolean} Whether or not the image has been converted to a false color image
   */
  convertImageToFalseColorImage(image: Image, colormap: ColormapID | ColormapObject): boolean;

  /**
   * Convert the image of a element to a false color image
   *
   * @param {HTMLElement} element The Cornerstone element
   * @param {ColormapID | ColormapObject} colormap It can be a colormap object or a colormap ID
   * @returns {boolean}  Whether or not the element's image has been converted to a false color image
   */
  convertToFalseColorImage(element: HTMLElement, colormap: ColormapID | ColormapObject): void;

  /**
   *  Disable an HTML element for further use in Cornerstone
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @returns {void}
   */
  disable(element: HTMLElement): void;

  /**
   * Sets a new image object for a given element.
   * Will also apply an optional viewport setting.
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @param {Image} image An Image loaded by a Cornerstone Image Loader
   * @param {Viewport} [viewport] A set of Cornerstone viewport parameters
   */
  displayImage(element: HTMLElement, image: Image, viewport?: Viewport): void;

  /**
   * Immediately draws the enabled element
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @returns {void}
   */
  draw(element: HTMLElement);

  /**
   * Internal API function to draw an image to a given enabled element
   *
   * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
   * @param {boolean} [invalidated=false] true if pixel data has been invalidated and cached rendering should not be used
   * @returns {void}
   */
  drawImage(enabledElement: EnabledElement, invalidated: boolean = false): void;

  /**
   * Draws all invalidated enabled elements and clears the invalid flag after drawing it
   *
   * @returns {void}
   */
  drawInvalidated();

  /**
   * Enable an HTML Element for use in Cornerstone
   *
   * - If there is a Canvas already present within the HTMLElement, and it has the class
   * 'cornerstone-canvas', this function will use this existing Canvas instead of creating
   * a new one. This may be helpful when using libraries (e.g. React, Vue) which don't
   * want third parties to change the DOM.
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @param {EnabledElementOptions} [options] Options for the enabledElement
   * @returns {void}
   */
  enable(element: HTMLElement, options?: EnableElementOptions);

  events: {
    listeners: Record<string, ((event: any) => void)[]>;
    namespaces: Record<string, (event: any) => void>;
  };

  /**
   * Adjusts an image's scale and translation so the image is centered and all pixels
   * in the image are viewable.
   *
   * @param {HTMLElement} element The Cornerstone element to update
   * @returns {void}
   */
  fitToWindow(element: HTMLElement);

  /**
   * Creates a LUT used while rendering to convert stored pixel values to display pixels
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {number} windowWidth The Window Width
   * @param {number} windowCenter The Window Center
   * @param {boolean} invert A boolean describing whether or not the image has been inverted
   * @param {ModalityLUT} [modalityLUT] A modality Lookup Table
   * @param {VOILUT} [voiLUT] A Volume of Interest Lookup Table
   * @returns {Uint8ClampedArray} A lookup table to apply to the image
   */
  generateLut(
    image: Image,
    windowWidth: number,
    windowCenter: number,
    invert: boolean,
    modalityLUT?: ModalityLUT,
    voiLUT?: VOILUT,
  ): Uint8ClampedArray;

  /**
   * Retrieve the currently active layer for a Cornerstone element
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {EnabledElementLayer} The currently active layer
   */
  getActiveLayer(element: HTMLElement): EnabledElementLayer;

  /**
   * Creates a new viewport object containing default values for the image and canvas
   *
   * @param {HTMLCanvasElement} canvas A Canvas DOM element
   * @param {Image} [image] A Cornerstone Image Object
   * @returns {Viewport} viewport object
   */
  getDefaultViewport(canvas: HTMLCanvasElement, image?: Image): Viewport;

  /**
   * Returns a default viewport for display the specified image on the specified
   * enabled element.  The default viewport is fit to window
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {Image} image A Cornerstone Image Object
   * @returns {Viewport} The default viewport for the image
   */
  getDefaultViewportForImage(element: HTMLElement, image: Image): Viewport;

  /**
   * Retrieves any data for a Cornerstone enabledElement for a specific string
   * dataType
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @param {string} dataType A string name for an arbitrary set of data
   * @returns {*} Whatever data is stored for this enabled element
   */
  getElementData(element: HTMLElement, dataType: string);

  /**
   * Retrieves a Cornerstone Enabled Element object
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @returns {EnabledElement} A Cornerstone Enabled Element
   */
  getEnabledElement(element: HTMLElement): EnabledElement;

  /**
   * Retrieve all of the currently enabled Cornerstone elements
   *
   * @returns {EnabledElement[]} An Array of Cornerstone enabledElement Objects
   */
  getEnabledElements(): EnableElement[];

  /**
   * Adds a Cornerstone Enabled Element object to the central store of enabledElements
   *
   * @param {string} imageId A Cornerstone Image ID
   * @returns {EnabledElement[]} An Array of Cornerstone enabledElement Objects
   */
  getEnabledElementsByImageId(imageId: string): EnabledElement[];

  /**
   * Returns the currently displayed image for an element or undefined if no image has been displayed yet
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {Image} The Cornerstone Image Object displayed in this element
   */
  getImage(element: HTMLElement): Image;

  /**
   * Retrieve a layer from a Cornerstone element given a layer ID
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {string} layerId The unique identifier for the layer
   * @returns {EnabledElementLayer | undefined} The layer
   */
  getLayer(element: HTMLElement, layerId: string): EnabledElementLayer | undefined;

  /**
   * Retrieve all layers for a Cornerstone element
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {EnabledElementLayer[]} An array of layers
   */
  getLayers(element: HTMLElement): EnabledElementLayer[];

  /**
   * Retrieves an array of pixels from a rectangular region with modality LUT transformation applied
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {number} x The x coordinate of the top left corner of the sampling rectangle in image coordinates
   * @param {number} y The y coordinate of the top left corner of the sampling rectangle in image coordinates
   * @param {number} width The width of the of the sampling rectangle in image coordinates
   * @param {number} height The height of the of the sampling rectangle in image coordinates
   * @returns {number[]} The modality pixel value of the pixels in the sampling rectangle
   */
  getPixels(element: HTMLElement, x: number, y: number, width: number, height: number): number[];

  /**
   * Retrieves an array of stored pixel values from a rectangular region of an image
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {number} x The x coordinate of the top left corner of the sampling rectangle in image coordinates
   * @param {number} y The y coordinate of the top left corner of the sampling rectangle in image coordinates
   * @param {number} width The width of the of the sampling rectangle in image coordinates
   * @param {number} height The height of the of the sampling rectangle in image coordinates
   * @returns {number[]} The stored pixel value of the pixels in the sampling rectangle
   */
  getStoredPixels(
    element: HTMLElement,
    x: number,
    y: number,
    width: number,
    height: number,
  ): number[];

  /**
   * Retrieves the viewport for the specified enabled element
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {Viewport | undefined} The Cornerstone Viewport settings for this element, if they exist. Otherwise, undefined
   */
  getViewport(element: HTMLElement): Viewport | undefined;

  /**
   * Retrieve all visible layers for a Cornerstone element
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {EnabledElementLayer[]} An array of layers
   */
  getVisibleLayers(element: HTMLElement): EnabledElementLayer[];

  imageCache: {
    /** Image cache dictionary */
    imageCache: ImageCacheDict;

    /** Cached image list */
    cachedImages: CachedImage[];

    /** Sets the maximum size of cache and purges cache contents if necessary.
     *
     * @param {number} numBytes The maximun size that the cache should occupy.
     * @returns {void}
     */
    setMaximumSizeBytes(numBytes: number): void;

    /**
     * Puts a new image loader into the cache
     *
     * @param {string} imageId ImageId of the image loader
     * @param {ImageLoadObject} imageLoadObject The object that is loading or loaded the image
     * @returns {void}
     */
    putImageLoadObject(imageId: string, imageLoadObject: ImageLoadObject);

    /**
     * Retuns the object that is loading a given imageId
     *
     * @param {string} imageId Image ID
     * @returns {ImageLoadObject | undefined} Image load object
     */
    getImageLoadObject(imageId: string): ImageLoadObject | undefined;

    /**
     * Removes the image loader associated with a given Id from the cache
     *
     * @param {string} imageId Image ID
     * @returns {void}
     */
    removeImageLoadObject(imageId: string): void;

    /**
     * Gets the current infomation of the image cache
     *
     * @returns {CacheInformation} Image cache infomation
     */
    getCacheInfo(): CacheInformation;

    /**
     * Removes all images from cache
     *
     * @returns {void}
     */
    purgeCache(): void;

    /**
     * Updates the space than an image is using in the cache
     *
     * @param {string} imageId Image ID
     * @param {number} newCacheSize New image size
     * @returns {void}
     */
    changeImageIdCacheSize(imageId: string, newCacheSize: number);
  };

  /** Internal APIs */
  internal: {
    Transform: Transform;

    /**
     * Calculate the transform for a Cornerstone enabled element
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element
     * @param {number} [scale] The viewport scale
     * @returns {Transform} The current transform
     */
    calculateTransform(enabledElement: EnabledElement, scale?: number): Transform;

    /**
     * Internal API function to draw an image to a given enabled element
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
     * @param {boolean} [invalidated=false] true if pixel data has been invalidated and cached rendering should not be used
     * @returns {void}
     */
    drawImage(enabledElement: EnabledElement, invalidated: boolean = false): void;

    /**
     * Creates a LUT used while rendering to convert stored pixel values to display pixels
     *
     * @param {Image} image A Cornerstone Image Object
     * @param {number} windowWidth The Window Width
     * @param {number} windowCenter The Window Center
     * @param {boolean} invert A boolean describing whether or not the image has been inverted
     * @param {ModalityLUT} [modalityLUT] A modality Lookup Table
     * @param {VOILUT} [voiLUT] A Volume of Interest Lookup Table
     * @returns {Uint8ClampedArray} A lookup table to apply to the image
     */
    generateLut(
      image: Image,
      windowWidth: number,
      windowCenter: number,
      invert: boolean,
      modalityLUT?: ModalityLUT,
      voiLUT?: VOILUT,
    ): Uint8ClampedArray;

    /**
     * Creates a new viewport object containing default values for the image and canvas
     *
     * @param {HTMLCanvasElement} canvas A Canvas DOM element
     * @param {Image} [image] A Cornerstone Image Object
     * @returns {Viewport} viewport object
     */
    getDefaultViewport(canvas: HTMLCanvasElement, image?: Image): Viewport;

    /**
     * Get transform of enabled element
     *
     * @param {EnabledElement} enabledElement Enabled element
     * @returns {Transform} transform
     */
    getTransform(enabledElement: EnabledElement): Transform;

    /**
     * Polyfills requestAnimationFrame for older browsers.
     *
     * @param {Function} callback A parameter specifying a function to call when it's time to update your animation for the next repaint. The callback has one single argument, a DOMHighResTimeStamp, which indicates the current time (the time returned from performance.now() ) for when requestAnimationFrame starts to fire callbacks.
     *
     * @returns {number} A long integer value, the request id, that uniquely identifies the entry in the callback list. This is a non-zero value, but you may not make any other assumptions about its value. You can pass this value to window.cancelAnimationFrame() to cancel the refresh callback request.
     */
    requestAnimationFrame(callback: FrameRequestCallback): number;

    /**
     * Sets new default values for `getDefaultViewport`
     *
     * @param {Viewport} viewport - Object that sets new default values for getDefaultViewport
     * @returns {void}
     */
    setDefaultViewport(viewport: Viewport): void;

    /**
     * Converts stored color pixel values to display pixel values using a LUT.
     *
     * Note: Skips alpha value for any input image pixel data.
     *
     * @param {Image} image A Cornerstone Image Object
     * @param {LUT} lut Lookup table array
     * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
     * @returns {void}
     */
    storedColorPixelDataToCanvasImageData(
      image: Image,
      lut: LUT,
      canvasImageDataData: Uint8ClampedArray,
    ): void;

    /**
     * This function transforms stored pixel values into a canvas image data buffer
     * by using a LUT.  This is the most performance sensitive code in cornerstone and
     * we use a special trick to make this go as fast as possible.  Specifically we
     * use the alpha channel only to control the luminance rather than the red, green and
     * blue channels which makes it over 3x faster. The canvasImageDataData buffer needs
     * to be previously filled with white pixels.
     *
     * NOTE: Attribution would be appreciated if you use this technique!
     *
     * @param {Image} image A Cornerstone Image Object
     * @param {LUT} lut Lookup table array
     * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
     * @returns {void}
     */
    storedPixelDataToCanvasImageData(
      image: Image,
      lut: LUT,
      canvasImageDataData: Uint8ClampedArray,
    ): void;

    /**
     * Converts stored color pixel values to display pixel values using a ColorLUT.
     *
     * @param {Image} image A Cornerstone Image Object
     * @param {LookupTable | ColorLUT} colorLut Lookup table array
     * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
     * @returns {void}
     */
    storedPixelDataToCanvasImageDataColorLUT(
      image: Image,
      colorLut: LookupTable | ColorLUT,
      canvasImageDataData: Uint8ClampedArray,
    ): void;

    /**
     * Converts stored color pixel values to display pixel values using a pseudocolor LUT.
     *
     * @param {Image} image A Cornerstone Image Object
     * @param {Array} grayscaleLut Lookup table array
     * @param {LookupTable|Array} colorLut Lookup table array
     * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
     *
     * @returns {void}
     */
    storedPixelDataToCanvasImageDataPseudocolorLUT(
      image: Image,
      grayscaleLut: GrayscaleLUT,
      colorLut: ColorLUT,
      canvasImageDataData: Uint8ClampedArray,
    ): void;

    /**
     * This function transforms stored pixel values into a canvas image data buffer
     * by using a LUT.
     *
     * @param {Image} image A Cornerstone Image Object
     * @param {Array} lut Lookup table array
     * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
     * @returns {void}
     */
    storedPixelDataToCanvasImageDataRGBA(
      image: Image,
      lut: LUT,
      canvasImageDataData: Uint8ClampedArray,
    ): void;
  };

  /**
   * Sets the invalid flag on the enabled element and fires an event
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {void}
   */
  invalidate(element: HTMLElement): void;

  /**
   * Forces the image to be updated/redrawn for all enabled elements
   * displaying the specified imageId
   *
   * @param {string} imageId The imageId of the Cornerstone Image Object to redraw
   * @returns {void}
   */
  invalidateImageId(imageId: string): void;

  /**
   * Loads an image given an imageId and optional priority and returns a promise which will resolve to
   * the loaded image object or fail if an error occurred. The image is stored in the cache.
   *
   * @param {string} imageId A Cornerstone Image Object's imageId
   * @param {ImageLoaderOptions} [options] Options to be passed to the Image Loader
   * @returns {ImageLoadObject} Image Loader Object
   */
  loadAndCacheImage(imageId: string, options?: ImageLoaderOptions): ImageLoadObject;

  /**
   * Loads an image given an imageId and optional priority and returns a promise which will resolve to
   * the loaded image object or fail if an error occurred.  The loaded image is not stored in the cache.
   *
   * @param {string} imageId A Cornerstone Image Object's imageId
   * @param {ImageLoaderOptions} [options] Options to be passed to the Image Loader
   * @returns {ImageLoadObject} An Object which can be used to act after an image is loaded or loading fails
   */
  loadImage(imageId: string, options?: ImageLoaderOptions): ImageLoadObject;

  metaData: {
    /**
     * Adds a metadata provider with the specified priority
     *
     * @param {MetadataProvider} provider Metadata provider function
     * @param {number} [priority=0] 0 is default/normal, > 0 is high, < 0 is low
     * @returns {void}
     */
    addProvider(provider: MetadataProvider, priority: number = 0): void;

    /**
     * Removes the specified provider
     *
     * @param {MetadataProvider} provider Metadata provider function
     * @returns {void}
     */
    removeProvider(provider: MetadataProvider): void;

    /** Gets metadata from the registered metadata providers. Will call each one from highest priority to lowest until one responds */
    get(type: string, imageId: string): any;
  };

  /**
   * Converts a point in the page coordinate system to the pixel coordinate system
   *
   * @param {HTMLElement} element The Cornerstone element within which the input point lies
   * @param {number} pageX The x value in the page coordinate system
   * @param {number} pageY The y value in the page coordinate system
   * @returns {Vec2} The transformed point in the pixel coordinate system
   */
  pageToPixel(element: HTMLElement, pageX: number, pageY: number): Vec2;

  /**
   * Converts the image pixel data into a false color data
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {LookupTable} lookupTable A lookup table Object
   * @returns {void}
   * @deprecated This function is superseded by the ability to set the Viewport parameters
   * to include colormaps.
   */
  pixelDataToFalseColorData(image: Image, lookupTable: LookupTable): void;

  /**
   * Converts a point in the pixel coordinate system to the canvas coordinate system
   * system.  This can be used to render using canvas context without having the weird
   * side effects that come from scaling and non square pixels
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @param {Vec2} point The transformed point in the pixel coordinate system
   * @returns {Vec2} The input point in the canvas coordinate system
   */
  pixelToCanvas(element: HTMLElement, point: Vec2): Vec2;

  /**
   * Purge the layers
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @returns {void}
   */
  purgeLayers(element: Element): void;

  /**
   * Registers an imageLoader plugin with cornerstone for the specified scheme
   *
   * @param {string} scheme The scheme to use for this image loader (e.g. 'dicomweb', 'wadouri', 'http')
   * @param {Function} imageLoader A Cornerstone Image Loader function
   * @returns {void}
   */
  registerImageLoader(schema: ImageLoaderSchema, imageLoader: ImageLoader): void;

  /**
   * Registers a new unknownImageLoader and returns the previous one
   *
   * @param {ImageLoader} imageLoader A Cornerstone Image Loader
   * @returns {ImageLoader | undefined} The previous Unknown Image Loader
   */
  registerUnknownImageLoader(imageLoader: ImageLoader): ImageLoader | undefined;

  /**
   * Clears any data for a Cornerstone enabledElement for a specific string
   * dataType
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @param {string} dataType A string name for an arbitrary set of data
   * @returns {void}
   */
  removeElementData(element: HTMLElement, dataType: string): void;

  /**
   * Remove a layer from a Cornerstone element given a layer ID
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {string} layerId The unique identifier for the layer
   * @returns {void}
   */
  removeLayer(element: HTMLElement, layerId: string): void;

  /**
   * API function to render a color image to an enabled element
   *
   * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
   * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
   * @returns {void}
   */
  renderColorImage(enabledElement: EnabledElement, invalidated: boolean): void;

  /**
   * API function to draw a grayscale image to a given enabledElement
   *
   * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
   * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
   * @returns {void}
   */
  renderGrayscaleImage(enabledElement: EnabledElement, invalidated: boolean): void;

  /**
   * API function to draw a label map image to a given enabledElement
   *
   * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
   * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
   * @returns {void}
   */
  renderLabelMapImage(enabledElement: EnabledElement, invalidated: boolean): void;

  /**
   * API function to draw a pseudo-color image to a given enabledElement
   *
   * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
   * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
   * @returns {void}
   */
  renderPseudoColorImage(enabledElement: EnabledElement, invalidated: boolean): void;

  /**
   * Render the image to the provided canvas immediately.
   *
   * @param {HTMLCanvasElement} canvas The HTML canvas where the image will be rendered.
   * @param {Image} image An Image loaded by a Cornerstone Image Loader
   * @param {Viewport} [viewport] A set of Cornerstone viewport parameters
   * @param {EnableElementOptions} [options] Options for rendering the image
   * @returns {void}
   */
  renderToCanvas(
    canvas: HTMLCanvasElement,
    image: Image,
    viewport?: Viewport,
    options?: EnableElementOptions,
  ): void;

  /**
   * API function to draw a standard web image (PNG, JPG) to an enabledImage
   *
   * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
   * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
   * @returns {void}
   */
  renderWebImage(enabledElement: EnabledElement, invalidated: boolean): void;

  rendering: {
    /**
     * API function to render a color image to an enabled element
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
     * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
     * @returns {void}
     */
    colorImage(enabledElement: EnabledElement, invalidated: boolean): void;

    /**
     * API function to draw a grayscale image to a given enabledElement
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
     * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
     * @returns {void}
     */
    grayscaleImage(enabledElement: EnabledElement, invalidated: boolean): void;

    /**
     * API function to draw a standard web image (PNG, JPG) to an enabledImage
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
     * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
     * @returns {void}
     */
    webImage(enabledElement: EnabledElement, invalidated: boolean): void;

    /**
     * API function to draw a pseudo-color image to a given enabledElement
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
     * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
     * @returns {void}
     */
    pseudoColorImage(enabledElement: EnabledElement, invalidated: boolean): void;

    /**
     * API function to draw a label map image to a given enabledElement
     *
     * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw
     * @param {boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used
     * @returns {void}
     */
    labelMapImage(enabledElement: EnabledElement, invalidated: boolean): void;

    /**
     * Render the image to the provided canvas immediately.
     *
     * @param {HTMLCanvasElement} canvas The HTML canvas where the image will be rendered.
     * @param {Image} image An Image loaded by a Cornerstone Image Loader
     * @param {Viewport} [viewport] A set of Cornerstone viewport parameters
     * @param {EnableElementOptions} [options] Options for rendering the image
     * @returns {void}
     */
    toCanvas(
      canvas: HTMLCanvasElement,
      image: Image,
      viewport?: Viewport,
      options?: EnableElementOptions,
    ): void;
  };

  /**
   * Polyfills requestAnimationFrame for older browsers.
   *
   * @param {Function} callback A parameter specifying a function to call when it's time to update your animation for the next repaint. The callback has one single argument, a DOMHighResTimeStamp, which indicates the current time (the time returned from performance.now() ) for when requestAnimationFrame starts to fire callbacks.
   *
   * @returns {number} A long integer value, the request id, that uniquely identifies the entry in the callback list. This is a non-zero value, but you may not make any other assumptions about its value. You can pass this value to window.cancelAnimationFrame() to cancel the refresh callback request.
   */
  requestAnimationFrame(callback: FrameRequestCallback): number;

  /**
   * Resets the viewport to the default settings
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @returns {void}
   */
  reset(element: HTMLElement): void;
  /**
   * Resizes an enabled element and optionally fits the image to window
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {boolean} [forceFitToWindow=false] true to to force a refit, false to rescale accordingly
   * @returns {void}
   */
  resize(element: HTMLElement, forceFitToWindow: boolean = false): void;

  /**
   * Restores a false color image to its original version
   *
   * @param {Image} image A Cornerstone Image Object
   * @returns {boolean} True if the image object had a valid restore function, which was run. Otherwise, false.
   */
  restoreImage(image: Image): boolean;

  /**
   * Set the active layer for a Cornerstone element
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {string} layerId The unique identifier for the layer
   * @returns {void}
   */
  setActiveLayer(element: HTMLElement, layerId: string): void;

  /**
   * Sets new default values for `getDefaultViewport`
   *
   * @param {Viewport} viewport - Object that sets new default values for getDefaultViewport
   * @returns {void}
   */
  setDefaultViewport(viewport: Viewport): void;

  /**
   * Set a new image for a specific layerId
   *
   * @param {HTMLElement} element The DOM element enabled for Cornerstone
   * @param {Image} image The image to be displayed in this layer
   * @param {string} [layerId] The unique identifier for the layer
   * @returns {void}
   */
  setLayerImage(element: HTMLElement, image: Image, layerId?: string): void;

  /**
   * Sets the canvas context transformation matrix to the pixel coordinate system.  This allows
   * geometry to be driven using the canvas context using coordinates in the pixel coordinate system
   *
   * @param {EnabledElement} enabledElement The
   * @param {CanvasRenderingContext2D} context The CanvasRenderingContext2D for the enabledElement's Canvas
   * @param {number} [scale] Optional scale to apply
   * @returns {void}
   */
  setToPixelCoordinateSystem(
    enabledElement: EnabledElement,
    context: CanvasRenderingContext2D,
    scale?: number,
  ): void;

  /**
   * Sets/updates viewport of a given enabled element
   *
   * @param {HTMLElement} element - DOM element of the enabled element
   * @param {Partial<Viewport>} [viewport] - Object containing the viewport properties
   * @returns {void}
   */
  setViewport(element: HTMLElement, viewport?: Partial<Viewport>): void;

  /**
   * Converts stored color pixel values to display pixel values using a LUT.
   *
   * Note: Skips alpha value for any input image pixel data.
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {LUT} lut Lookup table array
   * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
   * @returns {void}
   */
  storedColorPixelDataToCanvasImageData(
    image: Image,
    lut: LUT,
    canvasImageDataData: Uint8ClampedArray,
  ): void;

  /**
   * This function transforms stored pixel values into a canvas image data buffer
   * by using a LUT.  This is the most performance sensitive code in cornerstone and
   * we use a special trick to make this go as fast as possible.  Specifically we
   * use the alpha channel only to control the luminance rather than the red, green and
   * blue channels which makes it over 3x faster. The canvasImageDataData buffer needs
   * to be previously filled with white pixels.
   *
   * NOTE: Attribution would be appreciated if you use this technique!
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {LUT} lut Lookup table array
   * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
   * @returns {void}
   */
  storedPixelDataToCanvasImageData(
    image: Image,
    lut: LUT,
    canvasImageDataData: Uint8ClampedArray,
  ): void;

  /**
   * Converts stored color pixel values to display pixel values using a ColorLUT.
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {LookupTable | ColorLUT} colorLut Lookup table array
   * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
   * @returns {void}
   */
  storedPixelDataToCanvasImageDataColorLUT(
    image: Image,
    colorLut: LookupTable | ColorLUT,
    canvasImageDataData: Uint8ClampedArray,
  ): void;

  /**
   * Converts stored color pixel values to display pixel values using a pseudocolor LUT.
   *
   * @param {Image} image A Cornerstone Image Object
   * @param {Array} grayscaleLut Lookup table array
   * @param {LookupTable|Array} colorLut Lookup table array
   * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels
   *
   * @returns {void}
   */
  storedPixelDataToCanvasImageDataPseudocolorLUT(
    image: Image,
    grayscaleLut: GrayscaleLUT,
    colorLut: ColorLUT,
    canvasImageDataData: Uint8ClampedArray,
  ): void;

  /**
   * Trigger a CustomEvent
   *
   * @param {EventTarget} element The element or EventTarget to trigger the event upon
   * @param {string} type The event type name
   * @param {*} [detail=null] The event data to be sent
   * @returns {boolean} The return value is false if at least one event listener called preventDefault(). Otherwise it returns true.
   */
  triggerEvent(element: EventTarget, type: string, detail: any = null): boolean;

  /**
   * Forces the image to be updated/redrawn for the specified enabled element
   *
   * @param {HTMLElement} element An HTML Element enabled for Cornerstone
   * @param {boolean} [invalidated=false] Whether or not the image pixel data has been changed, necessitating a redraw
   *
   * @returns {void}
   */
  updateImage(element: HTMLElement, invalidated: boolean = false): void;

  webGL: {
    /**
     * Creates a program from 2 shaders source (Strings)
     *
     * @param  {WebGLRenderingContext} gl The WebGL context.
     * @param  {WebGLShader} vertexShaderSrc Vertex shader string
     * @param  {WebGLShader} fragShaderSrc Fragment shader string
     * @returns {WebGLProgram} A program
     */
    createProgramFromString(
      gl: WebGLRenderingContext,
      vertexShaderSrc: WebGLShader,
      fragShaderSrc: WebGLShader,
    ): WebGLProgram;

    isWebGLInitialized: boolean;

    renderer: {
      /**
       * Get render canvas
       *
       * @returns {HTMLCanvasElement} Render canvas
       */
      getRenderCanvas(): HTMLCanvasElement;

      /** Init renderer */
      initRenderer(): void;

      /**
       * Check is webgl available
       *
       * @returns {boolean} Is webgl available
       */
      isWebGLAvailable(): boolean;

      /**
       * Render enabled element
       *
       * @param {EnabledElement} enabledElement Enabled element
       * @returns {HTMLCanvasElement} Canvas element
       */
      render(enabledElement: EnabledElement): HTMLCanvasElement;
    };

    textureCache: {
      /**
       * Get image texture
       *
       * @param {string} imageId Image ID
       * @returns {ImageTexture | undefined} Image texture
       */
      getImageTexture(imageId: string): ImageTexture | undefined;

      /**
       * Purge texture cache
       *
       * @returns {void}
       */
      purgeCache(): void;

      /**
       * Put image texture to image object
       *
       * @param {Image} image Image object
       * @param {ImageTexture} imageTexture Image texture
       * @returns {void}
       */
      putImageTexture(image: IMage, imageTexture: ImageTexture): void;

      /**
       * Remove image texture
       *
       * @param {string} imageId - Image ID
       * @returns {ImageTexture} Image texture
       */
      removeImageTexture(imageId: string): ImageTexture;

      /**
       * Set maximum size bytes
       *
       * @param {number} numBytes Number of bytes
       * @returns {void}
       */
      setMaximumSizeBytes(numBytes: number): void;
    };
  };
}

declare const cornerstone: Cornerstone;

declare module '@dcm/cornerstone-core' {
  export = cornerstone;
}
