import type SpatialReferenceClass from "../geometry/SpatialReference.js";

/** @since 5.0 */
export type Color = [
    number,
    number,
    number,
    number
] | [
    number,
    number,
    number
];

/** @since 5.0 */
export type LabelPosition = "curved" | "parallel";

/** @since 5.0 */
export interface FeatureTemplatePrototype {
  /** @since 5.0 */
  attributes?: Record<string, any>;
}

/** @since 5.0 */
export interface FeatureTemplateThumbnail {
  /**
   * The MIME type of the image.
   *
   * @since 5.0
   */
  contentType: "png" | "jpg" | "jpeg" | "image";
  /**
   * The [base64EncodedImageData](https://developer.mozilla.org/docs/Web/API/WindowBase64/Base64_encoding_and_decoding)
   * presenting the thumbnail image.
   *
   * @since 5.0
   */
  imageData: string;
  /**
   * The width of the thumbnail.
   *
   * @since 5.0
   */
  width: number;
  /**
   * The height of the thumbnail.
   *
   * @since 5.0
   */
  height: number;
}

/**
 * Supported field types.
 *
 * @since 5.0
 */
export type FieldType = "esriFieldTypeSmallInteger" | "esriFieldTypeInteger" | "esriFieldTypeSingle" | "esriFieldTypeDouble" | "esriFieldTypeLong" | "esriFieldTypeString" | "esriFieldTypeDate" | "esriFieldTypeOID" | "esriFieldTypeGeometry" | "esriFieldTypeBlob" | "esriFieldTypeRaster" | "esriFieldTypeGUID" | "esriFieldTypeGlobalID" | "esriFieldTypeXML" | "esriFieldTypeBigInteger" | "esriFieldTypeDateOnly" | "esriFieldTypeTimeOnly" | "esriFieldTypeTimestampOffset";

/** @since 5.0 */
export interface Point {
  /**
   * The x coordinate of the anchor point, measured along the east/west axis.
   *
   * @since 5.0
   */
  x: number;
  /**
   * The y coordinate of the anchor point, measured along the north/south axis.
   *
   * @since 5.0
   */
  y: number;
  /**
   * The z coordinate of the camera position.
   *
   * @since 5.0
   */
  z?: number;
  /**
   * The m value of the camera position.
   *
   * @since 5.0
   */
  m?: number;
  /**
   * The spatial reference of the camera position. If not specified, the spatial reference of the video layer is used.
   *
   * @since 5.0
   */
  spatialReference?: SpatialReferenceClass | null;
}

/**
 * An envelope is a rectangle defined by a range of values for each coordinate and attribute.
 *
 * @since 5.0
 */
export interface Extent {
  /**
   * The minimum X value in the area of the envelope.
   *
   * @since 5.0
   */
  xmin: number;
  /**
   * The minimum Y value in the area of the envelope.
   *
   * @since 5.0
   */
  ymin: number;
  /**
   * The maximum X value in the area of the envelope.
   *
   * @since 5.0
   */
  xmax: number;
  /**
   * The maximum Y value in the area of the envelope.
   *
   * @since 5.0
   */
  ymax: number;
}

export type Coordinate = number[];

export type Coordinate2D = [
    number,
    number
];

export interface CircularArc {
  /**
   * The parameters of the arc:
   *
   * - End point
   * - Interior point
   */
  c: [
      endPoint: Coordinate,
      interiorPoint: Coordinate2D
  ];
}

/**
 * An elliptic arc definition.
 *
 * @see [EllipticArc4](https://developers.arcgis.com/javascript/latest/references/core/portal/jsonTypes/#EllipticArc4) for circular elliptic arcs by four parameters.
 */
export interface EllipticArc7 {
  /**
   * The parameters of the arc:
   *
   * - End point
   * - Center point
   * - Sweep flag: major (0) or minor (less than 180 degrees) (1)
   * - Orientation flag: counter-clockwise (0) or clockwise (1)
   * - Rotation angle in radians. Positive values in counter-clockwise direction.
   * - Length of the semi-major axis
   * - Ratio of minor to major axis
   */
  a: [
      endPoint: Coordinate,
      centerPoint: Coordinate2D,
      isMinor: 0 | 1,
      isClockwise: 0 | 1,
      rotation: number,
      semiMajor: number,
      minorToMajorRatio: number
  ];
}

/**
 * Elliptic arc definition representing a circular arc.
 *
 * This curve type is most commonly used to represent full circles.
 */
export interface EllipticArc4 {
  /**
   * The parameters of the arc:
   *
   * - End point
   * - Center point
   * - Sweep flag: major (0) or minor (less than 180 degrees) (1)
   * - Orientation flag: counter-clockwise (0) or clockwise (1)
   */
  a: [
      endPoint: Coordinate,
      centerPoint: Coordinate2D,
      isMinor: 0 | 1,
      isClockwise: 0 | 1
  ];
}

export type EllipticArc = EllipticArc7 | EllipticArc4;

/** A definition for a cubic bezier curve. */
export interface BezierCurve {
  /**
   * The parameters of the bezier curve:
   *
   * - End point
   * - Control point 1
   * - Control point 2
   */
  b: [
      endPoint: Coordinate,
      controlPoint1: Coordinate2D,
      controlPoint2: Coordinate2D
  ];
}

/**
 * Compact representation of a curve segment.
 *
 * All curve segments start from the end point of the previous segment.
 *
 * Note: this type includes plain [Coordinate](https://developers.arcgis.com/javascript/latest/references/core/portal/jsonTypes/#Coordinate) because
 * curve geometries may include straight line segments.
 *
 * @see [ArcGIS REST reference](https://developers.arcgis.com/rest/services-reference/enterprise/geometry-objects/#curve-objects)
 */
export type Curve = Coordinate | CircularArc | EllipticArc | BezierCurve;

/**
 * The **VideoServiceLayerInfo** defines layer information for video layers published within the same
 * video service.
 *
 * @since 5.0
 */
export interface VideoServiceLayerInfo {
  /**
   * The layer id of the video layer.
   *
   * @since 5.0
   */
  layerId: number;
  /**
   * The URL to the poster image for the video layer.
   *
   * @since 5.0
   */
  posterUrl: string;
  /**
   * The source type of the video layer.
   *
   * @since 5.0
   */
  sourceType: VideoSourceType;
  /**
   * The title of the video layer.
   *
   * @since 5.0
   */
  title: string;
  /**
   * The layer type. The type is always "Video Layer" for VideoLayers.
   *
   * @since 5.0
   */
  type: "Video Layer";
}

/** @since 5.0 */
export type VideoSourceType = "ondemand" | "livestream";

/** @since 5.0 */
export interface VideoGroundControlPoint {
  /**
   * The latitude.
   *
   * @since 5.0
   */
  lat: number;
  /**
   * The longitude.
   *
   * @since 5.0
   */
  lon: number;
  /**
   * The x coordinate in pixels.
   *
   * @since 5.0
   */
  x: number;
  /**
   * The y coordinate in pixels.
   *
   * @since 5.0
   */
  y: number;
}

/** @since 5.0 */
export type VideoQuality = "sd" | "hd" | "fhd" | "qhd" | "uhd";

/**
 * The **Codecs** is an object that represents the codecs used by the video layer.
 *
 * @since 5.0
 */
export interface Codecs {
  /**
   * The audio codec used in the video layer.
   *
   * @since 5.0
   */
  audio: string;
  /**
   * The text codec used in the video layer.
   *
   * @since 5.0
   */
  text: string;
  /**
   * The video codec used in the video layer.
   *
   * @since 5.0
   */
  video: string;
}

/**
 * The **CameraInfo** is an object that represents the camera information of the video layer.
 *
 * @since 4.34
 */
export interface VideoCameraInfo {
  /**
   * The far distance of the camera in meters.
   *
   * @since 5.0
   */
  farDistance: number;
  /**
   * The field of view of the camera in degrees.
   *
   * @since 5.0
   */
  fov: number;
  /**
   * The heading of the camera in degrees.
   *
   * @since 5.0
   */
  heading: number;
  /**
   * The height of the camera in meters.
   *
   * @since 5.0
   */
  height: number;
  /**
   * The near distance of the camera in meters.
   *
   * @since 5.0
   */
  nearDistance: number;
  /**
   * The position of the camera.
   *
   * @since 5.0
   */
  position: Point;
  /**
   * The tilt of the camera in degrees.
   *
   * @since 5.0
   */
  tilt: number;
}

/**
 * Represents the telemetry elements available for display customization.
 *
 * @since 5.1
 */
export interface TelemetryElementFilter {}

/**
 * A JSON Feature object that can be added to a [StreamLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/StreamLayer/) on the client by calling its
 * [sendMessageToClient()](https://developers.arcgis.com/javascript/latest/references/core/layers/StreamLayer/#sendMessageToClient) method.
 * It is an esri Feature JSON object as defined in the
 * [Feature object specification](https://developers.arcgis.com/documentation/common-data-types/feature-object.htm).
 *
 * @since 5.0
 */
export interface Feature {
  /**
   * A location of the received data containing x, y coordinates for points, paths for lines, and rings for polygons, along with
   * the spatial reference wkid.
   *
   * @since 5.0
   */
  geometry?: object | null;
  /**
   * Name-value pairs of fields and field values associated with the received data.
   *
   * @since 5.0
   */
  attributes: Record<string, any>;
}

/** @since 5.0 */
export type GeometryType = "esriGeometryPoint" | "esriGeometryPolyline" | "esriGeometryPolygon" | "esriGeometryEnvelope" | "esriGeometryMultiPatch" | "esriGeometryMultipoint";

/** @since 5.0 */
export interface SimpleTransformation {
  /**
   * the spatial reference well known id
   *
   * @since 5.0
   */
  wkid: number;
}

/** @since 5.0 */
export interface CompositeTransformation {
  /** @since 5.0 */
  geoTransforms: GeoTransform[];
}

/** @since 5.0 */
export interface GeoTransform {
  /**
   * the spatial reference well known id.
   *
   * @since 5.0
   */
  wkid: number;
  /**
   * indicates whether to transform forward or not.
   *
   * @since 5.0
   */
  transformForward: boolean;
}

/** @since 5.0 */
export type DatumTransformation = number | SimpleTransformation | CompositeTransformation;

/** @since 5.0 */
export type SQLFormat = "none" | "native" | "standard";

/** @since 5.0 */
export interface Progressor {
  /**
   * Progress message.
   *
   * @since 5.0
   */
  message: string;
  /**
   * Progress percentage.
   *
   * @since 5.0
   */
  percent?: number;
}

/** @since 5.0 */
export type FormElementType = "field" | "attachment" | "group" | "relationship" | "text" | "utilityNetworkAssociations";

/** @since 5.0 */
export type TimeResolution = "minutes" | "seconds";

/** @since 5.0 */
export type TimeResolutionMS = TimeResolution | "milliseconds";

/** @since 5.0 */
export type InputMethod = "any" | "capture" | "upload";

/** @since 5.0 */
export type FormAttachmentAssociationType = "any" | "exact" | "exactOrNone";

/** @since 5.0 */
export type GroupState = "collapsed" | "expanded";

/** @since 5.0 */
export type TextFormatType = "plain-text" | "markdown";

/** @since 5.0 */
export type FormExpressionReturnType = "boolean" | "date" | "number" | "string";

/** @since 5.0 */
export type TableElementType = "group" | "field" | "attachment" | "relationship";

/** @since 5.0 */
export type LayoutType = "basic-grid" | "chronological-mono-timeline" | "chronological-multi-timeline" | "geographic-organic-standard" | "hierarchical-bottom-to-top" | "hierarchical-top-to-bottom" | "organic-community" | "organic-fusiform" | "organic-leaf-circle" | "organic-standard" | "radial-node-centric" | "radial-root-centric" | "tree-bottom-to-top" | "tree-left-to-right" | "tree-right-to-left" | "tree-top-to-bottom";

/** @since 5.0 */
export type TimeDirection = "bottom" | "left" | "right" | "top";