import type Point from "../../geometry/Point.js";
import type { Clonable } from "../../core/Clonable.js";
import type { JSONSupportMixin } from "../../core/JSONSupport.js";
import type { ScreenPoint } from "../../core/types.js";
import type { ControlPointProperties } from "./ControlPoint.js";
import type { ControlPoints } from "./types.js";

export interface ControlPointsGeoreferenceProperties extends Partial<Pick<ControlPointsGeoreference, "height" | "width">> {
  /**
   * An array of two, three, or four [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints) positions the media element.
   * The element is positioned, scaled, and rotated with two [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints).
   * Additionally, it will be skewed with three [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints).
   * With four [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints), a perspective transformation is applied to the element.
   *
   * @example
   * const swCorner = {
   *     sourcePoint: { x: 80, y: 1732 },
   *     mapPoint: new Point({ x: -107.875, y: 37.875, spatialReference })
   * };
   *
   * const neCorner = {
   *    sourcePoint: { x: 1353, y: 99 },
   *    mapPoint: new Point({ x: -107.75, y: 38, spatialReference })
   * };
   *
   * const controlPoints = [swCorner, neCorner];
   */
  controlPoints?: [
      ControlPointProperties,
      ControlPointProperties
  ] | [
      ControlPointProperties,
      ControlPointProperties,
      ControlPointProperties
  ] | [
      ControlPointProperties,
      ControlPointProperties,
      ControlPointProperties,
      ControlPointProperties
  ] | null;
}

/**
 * ControlPointsGeoreference is used to set the [geographic location](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ImageElement/#georeference) of the
 * [ImageElement](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ImageElement/) or [VideoElement](https://developers.arcgis.com/javascript/latest/references/core/layers/support/VideoElement/) referenced
 * in the [MediaLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/MediaLayer/) using the [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints), [width](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#width), and [height](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#height) parameters.
 * The element is positioned, scaled, and rotated with two [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints).
 * Additionally, it will be skewed with three [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints).
 * With four [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints), a perspective transformation is applied to the element.
 *
 * ```js
 * // the spatial reference for the MediaLayer, North American Datum 1927
 * const spatialReference = new SpatialReference({ wkid: 4267 });
 *
 * // create an array of four control points composed of a sourcePoint, a point
 * // on the image element in pixels, and a mapPoint which is the location of the
 * // sourcePoint in map space
 * const swCorner = {
 *     sourcePoint: { x: 80, y: 1732 },
 *     mapPoint: new Point({ x: -107.875, y: 37.875, spatialReference })
 * };
 *
 * const nwCorner = {
 *     sourcePoint: { x: 75, y: 102 },
 *     mapPoint: new Point({ x: -107.875, y: 38, spatialReference })
 * };
 *
 * const neCorner = {
 *    sourcePoint: { x: 1353, y: 99 },
 *    mapPoint: new Point({ x: -107.75, y: 38, spatialReference })
 * };
 *
 * const seCorner = {
 *    sourcePoint: { x: 1361, y: 1721 },
 *    mapPoint: new Point({ x: -107.75, y: 37.875, spatialReference })
 * };
 *
 * const controlPoints = [swCorner, nwCorner, neCorner, seCorner];
 *
 * // georeference for the imageElement using the control points,
 * // image width, and image height
 * const georeference = new ControlPointsGeoreference({ controlPoints, width: 1991, height: 2500 });
 *
 * const imageElement = new ImageElement({
 *     image: "https://jsapi.maps.arcgis.com/sharing/rest/content/items/1a3df04e7d734535a3a6a09dfec5a6b2/data",
 *     georeference
 * });
 *
 * // create a MediaLayer using the georeferenced ImageElement
 * const mediaLayer = new MediaLayer({
 *     source: [imageElement],
 *     title: "Geologic Map of the Telluride Quadrangle, Southwestern Colorado",
 *     copyright: "Wilbur S Burbank and Robert G. Luedke, 1966",
 *     opacity: 0.5,
 *     spatialReference
 * });
 * ```
 *
 * @since 4.25
 * @see [Sample - MediaLayer with control points](https://developers.arcgis.com/javascript/latest/sample-code/layers-medialayer-control-points/)
 * @see [ImageElement.georeference](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ImageElement/#georeference)
 * @see [VideoElement.georeference](https://developers.arcgis.com/javascript/latest/references/core/layers/support/VideoElement/#georeference)
 */
export default class ControlPointsGeoreference extends ControlPointsGeoreferenceSuperclass {
  constructor(properties?: ControlPointsGeoreferenceProperties);
  /**
   * An array of two, three, or four [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints) positions the media element.
   * The element is positioned, scaled, and rotated with two [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints).
   * Additionally, it will be skewed with three [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints).
   * With four [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints), a perspective transformation is applied to the element.
   *
   * @example
   * const swCorner = {
   *     sourcePoint: { x: 80, y: 1732 },
   *     mapPoint: new Point({ x: -107.875, y: 37.875, spatialReference })
   * };
   *
   * const neCorner = {
   *    sourcePoint: { x: 1353, y: 99 },
   *    mapPoint: new Point({ x: -107.75, y: 38, spatialReference })
   * };
   *
   * const controlPoints = [swCorner, neCorner];
   */
  get controlPoints(): ControlPoints | null | undefined;
  set controlPoints(value: [
      ControlPointProperties,
      ControlPointProperties
  ] | [
      ControlPointProperties,
      ControlPointProperties,
      ControlPointProperties
  ] | [
      ControlPointProperties,
      ControlPointProperties,
      ControlPointProperties,
      ControlPointProperties
  ] | null | undefined);
  /**
   * Defines the size of the element displayed, typically the element's height in pixels.
   * This property is used alongside [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints) and [width](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#width) to position the element.
   *
   * @default 0
   */
  accessor height: number;
  readonly type: "control-points";
  /**
   * Defines the size of the element displayed, typically the element's width in pixels.
   * This property is used alongside [controlPoints](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#controlPoints) and [height](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ControlPointsGeoreference/#height) to position the element.
   *
   * @default 0
   */
  accessor width: number;
  /**
   * Converts the given [ScreenPoint](https://developers.arcgis.com/javascript/latest/references/core/core/types/#ScreenPoint) to a [mapPoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/).
   * The [ScreenPoint](https://developers.arcgis.com/javascript/latest/references/core/core/types/#ScreenPoint) represents a point in terms
   * of pixels relative to the top-left corner of the element.
   *
   * @param sourcePoint - The location on the element.
   * @returns The [mapPoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/) corresponding to the given [ScreenPoint](https://developers.arcgis.com/javascript/latest/references/core/core/types/#ScreenPoint), in the spatial reference found in the [mapPoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/) of the first control point.
   * @example const mapPoint = controlPointGeoreference.toMap({x: 100, y: 250})
   */
  toMap(sourcePoint: ScreenPoint | null | undefined): Point | null | undefined;
  /**
   * Converts the given [mapPoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/) to a
   * [ScreenPoint](https://developers.arcgis.com/javascript/latest/references/core/core/types/#ScreenPoint).
   * The [ScreenPoint](https://developers.arcgis.com/javascript/latest/references/core/core/types/#ScreenPoint) represents a point in terms
   * of pixels relative to the top-left corner of the element.
   *
   * @param point - A point geometry.
   *   In the case where the point is not in the same spatial reference as the one in the [mapPoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/) of the first control point,
   *   it will be reprojected. The [projectOperator](https://developers.arcgis.com/javascript/latest/references/core/geometry/operators/projectOperator/) would need to be loaded to perform the reprojection, otherwise `null` is returned.
   * @returns The location on the element corresponding to the given [mapPoint](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/).
   * @example
   * // North_American_Datum_1927
   * const spatialReference = new SpatialReference({ wkid: 4267 });
   * const sourcePoint = controlPointGeoreference.toSource(new Point({ x: -107.875, y: 37.875, spatialReference }))
   */
  toSource(point: Point | null | undefined): ScreenPoint | null | undefined;
}
declare const ControlPointsGeoreferenceSuperclass: typeof Clonable & typeof JSONSupportMixin