import type Layer from "../../layers/Layer.js";
import type FeatureLayerView from "../layers/FeatureLayerView.js";
import type GeoJSONLayerView from "../layers/GeoJSONLayerView.js";
import type GeoRSSLayerView from "../layers/GeoRSSLayerView.js";
import type GraphicsLayerView from "../layers/GraphicsLayerView.js";
import type ImageryLayerView from "../layers/ImageryLayerView.js";
import type KMLLayerView from "../layers/KMLLayerView.js";
import type MediaLayerView from "../layers/MediaLayerView.js";
import type ParquetLayerView from "../layers/ParquetLayerView.js";
import type WFSLayerView from "../layers/WFSLayerView.js";
import type { OGCFeatureLayerView } from "../layers/OGCFeatureLayerView.js";
import type { StreamLayerView } from "../layers/StreamLayerView.js";

export interface LayerView2DMap {
  "base-dynamic": never;
  "base-elevation": never;
  "base-tile": never;
  "bing-maps": never;
  "building-scene": never;
  catalog: never;
  "catalog-dynamic-group": never;
  "catalog-footprint": never;
  csv: FeatureLayerView;
  dimension: never;
  elevation: never;
  feature: FeatureLayerView;
  "gaussian-splat": never;
  "geo-rss": GeoRSSLayerView;
  geojson: GeoJSONLayerView;
  graphics: GraphicsLayerView;
  group: never;
  imagery: ImageryLayerView;
  "imagery-tile": never;
  "integrated-mesh": never;
  "integrated-mesh-3dtiles": never;
  kml: KMLLayerView;
  "knowledge-graph": never;
  "knowledge-graph-sublayer": never;
  "line-of-sight": never;
  "link-chart": never;
  "map-image": never;
  "map-notes": never;
  media: MediaLayerView;
  "ogc-feature": OGCFeatureLayerView;
  "open-street-map": never;
  "oriented-imagery": never;
  parquet: ParquetLayerView;
  "point-cloud": never;
  route: never;
  scene: never;
  stream: StreamLayerView;
  "subtype-group": never;
  tile: never;
  unknown: never;
  unsupported: never;
  "vector-tile": never;
  video: never;
  viewshed: never;
  voxel: never;
  wcs: never;
  "web-tile": never;
  wfs: WFSLayerView;
  wms: never;
  wmts: never;
}

export type LayerView2DFor<TLayer extends Layer> = LayerView2DMap[TLayer["type"]];

/**
 * A vertex of a tessellated mesh.
 *
 * There are five different tessellation algorithms, one for each supported geometry type. The attributes in a
 * vertex can be used to populate vertex and index buffers that can be rendered using appropriate shaders.
 * See the [SDK sample](https://developers.arcgis.com/javascript/latest/sample-code/custom-gl-tessellation-helpers/) for a possible way of
 * doing this using a single universal shader program that can render any of the supported geometry types.
 *
 * There are four attributes; the first three are 2D points, and the last one is a scalar value. In total
 * a mesh vertex contains 7 numeric values.
 *
 * **Geographic position (x, y)**
 * The geographic point associated to that vertex. For [Extent](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Extent.html) and [Polygon](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polygon.html)
 * is equivalent to the position of the vertex itself; for [Point](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Point.html) and [Multipoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Multipoint.html)
 * is the geographic position of the point, and the anchor that will be associated to the corresponding marker symbol;
 * for [Polyline](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html) it lies on the centerline. The geographic position is usually expressed in map units and a
 * custom vertex shader will generally need to transform it to
 * [normalized device coordinates](https://learnopengl.com/Getting-started/Coordinate-Systems).
 *
 * **Offset vector (xOffset, yOffset)**
 * This is an offset that is generally expressed in units other than the view's ones, and drives the extrusion of the geographic
 * position into lines and quads. For [Extent](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Extent.html) and [Polygon](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polygon.html)
 * is zero; for [Point](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Point.html) and [Multipoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Multipoint.html) it goes from the anchor
 * to the four vertices of the quad on screen; for [Polyline](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html) it goes from the centerline
 * to a vertex on the polyline's edge. The offset vector is usually expressed in some other units than map
 * and will not need to be transformed by the same transform used for the geographic position. A common convention
 * is to express the offset in points or pixels and code the vertex shader accordingly.
 *
 * ![tessellation-helpers-extrusion](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/tessellation-helpers-extrusion.png)
 *
 * **Texture coordinates (uTexcoord, vTexcoord)**
 * The texture coordinates associated to this vertex.
 * For [Extent](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Extent.html) the lower left vertex has coordinates (0, 0) and the upper right (1, 1); for
 * [Polygon](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polygon.html) the coordinates at each vertex match the interpolated coordinates that the
 * smallest enclosing extent for that polygon would have at the same fragment; for [Point](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Point.html) and
 * [Multipoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Multipoint.html) each quad has (0, 0) as the lower left texture coordinate and (1, 1) as the
 * upper right one; for [Polyline](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html) the start cap is made of two vertices with texture
 * coordinates (0, 0) and (0, 1) while the end cap is associated to (1, 0) and (1, 1).
 *
 * ![tessellation-helpers-uv](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/tessellation-helpers-uv.png)
 *
 * **Distance**
 * Valid only for [Polyline](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Polyline.html); it is the distance, in map units, from the beginning of the
 * polyline to this vertex.
 *
 * ![tessellation-helpers-distance](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/tessellation-helpers-distance.png)
 */
export interface MeshVertex {
  /**
   * The distance parameter for this vertex; this only applies when tessellating polylines. It starts
   * from 0 and runs up to the total length of the polyline. It is expressed in map units.
   */
  distance: number;
  /** The `u`-coordinate for texture mapping. It varies between 0 and 1 horizontally for quads and polygons, and along the entire length of a polyline. */
  uTexcoord: number;
  /** The `v`-coordinate for texture mapping. It varies between 0 and 1 vertically for quads and polygons, and across the width of a polyline. */
  vTexcoord: number;
  /** The `x`-coordinate, expressed in the same units as the [MapView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html). */
  x: number;
  /** The `x`-offset in screen space; this is used to extrude points (into quads), markers and polylines, and is 0 for polygons. */
  xOffset: number;
  /** The `y`-coordinate, expressed in the same units as the [MapView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html). */
  y: number;
  /** The `y`-offset in screen space; this is used to extrude points (into quads), markers and polylines, and is 0 for polygons. */
  yOffset: number;
}

/**
 * The triangle mesh resulting from a tessellation operation.
 *
 * An instance of `Mesh` can be obtained by calling one of the [BaseLayerViewGL2D](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-2d-layers-BaseLayerViewGL2D.html)
 * `tessellate*` methods and passing an instance of [Geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Geometry.html).
 */
export interface TessellatedMesh {
  /**
   * The indices of the triangles that connect vertices together;
   * each consecutive triplet of indices denotes a triangle.
   */
  indices: number[];
  /**
   * The vertices that make up the mesh.
   * Each element is a {@link views/2d/layers/support/types!MeshVertex}.
   */
  vertices: MeshVertex[];
}

export type ResizeAlign = "bottom" | "bottom-left" | "bottom-right" | "center" | "left" | "right" | "top" | "top-left" | "top-right";