import type MeshMaterial from "./MeshMaterial.js";
import type MeshMaterialMetallicRoughness from "./MeshMaterialMetallicRoughness.js";
import type { ClonableMixin } from "../../core/Clonable.js";
import type { JSONSupport } from "../../core/JSONSupport.js";
import type { MeshMaterialProperties } from "./MeshMaterial.js";
import type { MeshMaterialMetallicRoughnessProperties } from "./MeshMaterialMetallicRoughness.js";

export interface MeshComponentProperties extends Partial<Pick<MeshComponent, "name" | "shading">> {
  /**
   * A flat array of indices that refer to vertices in the
   * [Mesh.vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes) of the
   * mesh to which the component belongs. Each triple of indices defines a triangle
   * to render (i.e. the faces array must always have a length that is a multiple of 3).
   * Note that the indices refer to **vertices** and not to the index of the first coordinate
   * of a vertex in the [vertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes)
   * array.
   *
   * If faces is `null`, then all the vertices in the mesh will be rendered
   * as triangles for this component.
   *
   * @example
   * let mesh = new Mesh({
   *   vertexAttributes: {
   *     position: [
   *       2.336006, 48.860818, 0,
   *       2.336172, 48.861114, 0,
   *       2.335724, 48.861229, 0,
   *       2.335563, 48.860922, 0
   *     ]
   *   },
   *   // Create two components so we can have separate materials
   *   // for the two triangles that we want to render.
   *   components: [
   *     {
   *       faces: [0, 1, 2],
   *       material: {
   *         color: "red"
   *       }
   *     },
   *     {
   *       faces: [0, 2, 3],
   *       material: {
   *         color: "green"
   *       }
   *     }
   *   ]
   * });
   */
  faces?: Uint16Array | Uint32Array | null;
  /** The material determines how the component is visualized. */
  material?: MeshMaterialProperties | MeshMaterialMetallicRoughnessProperties | null;
}

/**
 * The MeshComponent class is used to apply one or more materials to
 * a single [Mesh](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/). The [faces](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/#faces) property
 * is a flat array of indices in the mesh
 * [Mesh.vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes) and defines the region
 * of vertices in the mesh on which to apply the material.
 * Each triple of values in the flat array of indices specifies a triangle to be rendered.
 *
 * To define the material for the whole mesh, [faces](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/#faces) may be set to `null`,
 * which indicates that all the vertices defined for the mesh should be rendered
 * as consecutive triangles.
 *
 * A mesh component defines a [material](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/#material) that determines how the region
 * of triangles is colored. This mesh color can either be a single value or
 * an image that is mapped to the vertices by means of the uv coordinates specified
 * in the mesh [Mesh.vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes).
 * The [shading](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/#shading) specifies the type of normals that are used to calculate how
 * lighting affects mesh coloring.
 *
 * Mesh components can be added to the [Mesh.components[]](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#components)
 * array.
 *
 * ```js
 * let component1 = new MeshComponent({
 *   // Indices refer to vertices specified in the mesh vertexAttributes.
 *   // Here we refer to 2 triangles composed of the first 6 vertices of the mesh.
 *   faces: [0, 1, 2, 3, 4, 5],
 *
 *   material: {
 *     color: "green"
 *   }
 * });
 *
 * let component2 = new MeshComponent({
 *   faces: [6, 7, 8, 9, 10, 11],
 *
 *   material: {
 *     color: "red"
 *   },
 *
 *   shading: "smooth"
 * });
 *
 * let mesh = new Mesh({
 *   // ... specify vertex attributes
 *
 *   components: [component1, component2]
 * });
 * ```
 *
 * @since 4.7
 * @see [Mesh](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/)
 */
export default class MeshComponent extends MeshComponentSuperclass {
  constructor(properties?: MeshComponentProperties);
  /**
   * A flat array of indices that refer to vertices in the
   * [Mesh.vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes) of the
   * mesh to which the component belongs. Each triple of indices defines a triangle
   * to render (i.e. the faces array must always have a length that is a multiple of 3).
   * Note that the indices refer to **vertices** and not to the index of the first coordinate
   * of a vertex in the [vertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes)
   * array.
   *
   * If faces is `null`, then all the vertices in the mesh will be rendered
   * as triangles for this component.
   *
   * @example
   * let mesh = new Mesh({
   *   vertexAttributes: {
   *     position: [
   *       2.336006, 48.860818, 0,
   *       2.336172, 48.861114, 0,
   *       2.335724, 48.861229, 0,
   *       2.335563, 48.860922, 0
   *     ]
   *   },
   *   // Create two components so we can have separate materials
   *   // for the two triangles that we want to render.
   *   components: [
   *     {
   *       faces: [0, 1, 2],
   *       material: {
   *         color: "red"
   *       }
   *     },
   *     {
   *       faces: [0, 2, 3],
   *       material: {
   *         color: "green"
   *       }
   *     }
   *   ]
   * });
   */
  get faces(): Uint32Array<ArrayBuffer> | null | undefined;
  set faces(value: Uint16Array | Uint32Array | null | undefined);
  /** The material determines how the component is visualized. */
  get material(): MeshMaterial | MeshMaterialMetallicRoughness | null | undefined;
  set material(value: MeshMaterialProperties | MeshMaterialMetallicRoughnessProperties | null | undefined);
  /**
   * Specifies a name of the component. The component name can be used to identify the component. Meshes created from
   * glTF will have components with names that correspond to mesh names from the glTF.
   *
   * @see [Mesh.createFromGLTF()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#createFromGLTF)
   */
  accessor name: string | null | undefined;
  /**
   * Specifies the type of normals used for lighting. This determines whether the object
   * has a smooth or an angular appearance. The following shading types are supported:
   *
   * | Type | Description |
   * |------|-------------|
   * | source | Shading uses the normals as defined in the vertex attributes. If no normals are defined, then shading defaults back to `flat` |
   * | flat | Shading uses normals created per triangle face. This type of shading is good for objects with sharp edges such as boxes. |
   * | smooth | Shading uses per-vertex normals that average the normals of all the faces a vertex is a part of. This type of shading is good for meshes that approximate curved surfaces such as spheres. |
   *
   * @default "source"
   */
  accessor shading: MeshComponentShading;
}
declare const MeshComponentSuperclass: typeof JSONSupport & typeof ClonableMixin

export type MeshComponentShading = "source" | "flat" | "smooth";