import type Color from "../Color.js";
import type Symbol from "./Symbol.js";
import type { CIMSymbolReference } from "./cim/types.js";
import type { SymbolProperties } from "./Symbol.js";

export interface CIMSymbolProperties extends SymbolProperties, Partial<Pick<CIMSymbol, "data">> {
  /**
   * > [!WARNING]
   * >
   * > The `color` property on CIMSymbol has no effect. CIMSymbols are a reference to a symbol defined in the `data` property, and the symbol's color should be set by configuring the color on the symbol layers within the `data` property.
   * > The color property is present for consistency with other
   * > symbol types.
   *
   * @example
   * // CSS color string
   * symbol.color = "dodgerblue";
   * @example
   * // HEX string
   * symbol.color = "#33cc33";
   * @example
   * // array of RGBA values
   * symbol.color = [51, 204, 51, 0.3];
   * @example
   * // object with rgba properties
   * symbol.color = {
   *   r: 51,
   *   g: 51,
   *   b: 204,
   *   a: 0.7
   * };
   */
  color?: Color;
}

/**
 * CIMSymbols are high quality, scalable, multi-layer vector symbols for features and graphics. They allow the user to add more customizations to their symbols,
 *  using one or more [symbol layers](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolLayer) to create unique symbols.
 * CIMSymbols can be created from [CIMSymbolReference JSON](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolReference)
 * that complies with the [CIM specification](https://github.com/Esri/cim-spec/blob/master/docs/v2/Types.md#symbol)
 * by passing the JSON to the [data](https://developers.arcgis.com/javascript/latest/references/core/symbols/CIMSymbol/#data) property. Not everything in the
 * [CIM specification](https://github.com/Esri/cim-spec/blob/master/docs/v2/Types.md#symbol) is currently supported in
 * the ArcGIS Maps SDK for JavaScript. The documentation on this page details the current support in the API.
 *
 * - [Symbol and symbol layer types](https://developers.arcgis.com/javascript/latest/references/core/symbols/CIMSymbol/#symbol-and-symbol-layer-types)
 * - [Primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/CIMSymbol/#primitive-overrides)
 * - [Animations](https://developers.arcgis.com/javascript/latest/references/core/symbols/CIMSymbol/#animations)
 *
 * <span id="symbol-and-symbol-layer-types"></span>
 * ### Symbol and symbol layer types
 *
 * The `symbol` property in the `CIMSymbolReference` can be of type [CIMPointSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPointSymbol), [CIMLineSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMLineSymbol), or [CIMPolygonSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPolygonSymbol).
 * Each symbol is made up of one or more [symbolLayers](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolLayer). Symbol layers are the building blocks of CIM symbols,
 * they combine to make rich graphical depictions. You can configure the shape, color, texture, size, position, etc of each symbol layer,
 * and combine multiple symbol layers to create your desired symbol. The [Symbol Builder](https://developers.arcgis.com/javascript/latest/symbol-builder/) provides a simple user interface
 * to experiment with symbol layers and their properties.
 *
 * All CIMSymbols have at least one symbol layer, but can have more, as outlined in the following table:
 *
 * <table>
 * <tbody>
 * 		<tr>
 * 			<th>Symbol type</th>
 *  		<th>Typical symbol layers</th>
 * 			<th>Role</th>
 * 		</tr>
 * 		<tr>
 * 			<td><a href="#CIMPointSymbol">CIMPointSymbol</a></td>
 * 			<td>Marker layers: <a href="#CIMVectorMarker">CIMVectorMarker</a>, <a href="#CIMPictureMarker">CIMPictureMarker</a></td>
 * 			<td>Draw relative to the point geometry</td>
 * 		</tr>
 * 		<tr>
 * 			<td rowspan="2"><a href="#CIMLineSymbol">CIMLineSymbol</a></td>
 * 			<td>Marker layers: <a href="#CIMVectorMarker">CIMVectorMarker</a>, <a href="#CIMPictureMarker">CIMPictureMarker</a></td>
 * 			<td>Draw at specified locations relative to the line geometry.</td>
 * 		</tr>
 * 		<tr>
 * 			<td>Stroke layers: <a href="#CIMSolidStroke">CIMSolidStroke</a>, <a href="#CIMPictureStroke">CIMPictureStroke</a>, <a href="#CIMGradientStroke">CIMGradientStroke</a></td>
 * 			<td>Draw relative to the line geometry. </td>
 * 		</tr>
 * 		<tr>
 * 			<td rowspan="3"><a href="#CIMPolygonSymbol">CIMPolygonSymbol</a></td>
 * 			<td>Marker layers: <a href="#CIMVectorMarker">CIMVectorMarker</a>, <a href="#CIMPictureMarker">CIMPictureMarker</a></td>
 * 			<td>Draw relative to the polygon outline or within the polygon interior, depending on the marker placement setting.</td>
 * 		</tr>
 * 		<tr>
 * 			<td>Stroke layers: <a href="#CIMSolidStroke">CIMSolidStroke</a>, <a href="#CIMPictureStroke">CIMPictureStroke</a>, <a href="#CIMGradientStroke">CIMGradientStroke</a></td>
 * 			<td>Draw relative to the polygon outline. </td>
 * 		</tr>
 * 		<tr>
 * 			<td>Fill layers: <a href="#CIMSolidFill">CIMSolidFill</a>, <a href="#CIMHatchFill">CIMHatchFill</a>, <a href="#CIMPictureFill">CIMPictureFill</a>, <a href="#CIMGradientFill">CIMGradientFill</a></td>
 * 			<td>Draw relative to the polygon interior.</td>
 * 		</tr>
 * 	</tbody>
 * </table>
 *
 * <span id="primitive-overrides"></span>
 * ### Primitive overrides
 *
 * [Primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPrimitiveOverride) allow you to use [Arcade expressions](https://developers.arcgis.com/javascript/latest/arcade/#visualization) to dynamically change many symbol layer properties
 * from attribute values in your data. Primitive overrides are defined on the `primitiveOverrides` property in the `CIMSymbolReference` - this property takes in an array of objects,
 * each object representing a primitive override on a specific symbol layer.
 *
 * <details>
 * <summary>Read More</summary>
 *
 * Below is an example of a CIMSymbol with a primitive override that changes the color of a symbol layer based on the value of the `DailyTraffic` attribute on each feature.
 *
 * ```js
 * const symbol = new CIMSymbol({
 *  data: {
 *   type: "CIMSymbolReference",
 *   primitiveOverrides: [{
 *     type: "CIMPrimitiveOverride",
 *     // primitiveName matches the primitiveName on the symbol layer
 *     primitiveName: "symbol-layer-1",
 *     propertyName: "Color", // property to be overridden
 *     valueExpressionInfo: {
 *       type: "CIMExpressionInfo",
 *       // colors the symbol layer red if the DailyTraffic is greater than 10,000, orange otherwise
 *       expression: `IIF($feature.DailyTraffic > 10000, "rgba(255,0,0,1)", "rgba(255,165,0,1)")`,
 *       returnType: "Default"
 *     }
 *   }],
 *   symbol: {
 *     type: "CIMLineSymbol",
 *     symbolLayers: [
 *      {
 *        type: "CIMSolidStroke",
 *        // primitiveName matches the primitiveName on the primitive override
 *        primitiveName: "symbol-layer-1",
 *        enable: true,
 *        // the property to be overridden
 *        color: [0, 0, 0, 255],
 *        width: 2
 *      },
 *      // other symbol layers
 *    ]
 *   }
 *  }
 * });
 * ```
 *
 * </details>
 *
 * See [Primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPrimitiveOverride) for more information.
 *
 * <span id="animations"></span>
 * ### Animations
 *
 * _Since 4.31_
 *
 * Symbol animations can be used to highlight freshness of data or draw attention to specific features. In CIMSymbol, animations can be defined on the symbol level (global animations) or on the symbol layer level. Global animations are applied to the entire symbol, while symbol layer animations are applied to a specific symbol layer in the symbol.
 * Similar to other symbol properties, animation properties can be overridden based on attribute values using [primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPrimitiveOverride).
 *
 * The following animation types are supported:
 * - [Color](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolAnimationColor)
 * - [Offset](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolAnimationOffset)
 * - [Rotation](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolAnimationRotation)
 * - [Scale](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolAnimationScale)
 * - [Size](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolAnimationSize)
 * - [Transparency](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolAnimationTransparency)
 *
 * #### Global animations
 * Global animations are currently only supported on [CIMPointSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPointSymbol)s. They are defined on the `animations` property of the `CIMPointSymbol` and are applied to the entire symbol.
 *
 * ```js
 * const symbol = new CIMSymbol({
 *  data: {
 *   type: "CIMSymbolReference",
 *   symbol: {
 *     type: "CIMPointSymbol",
 *     animations: [{ ... }], // global animation applied to the entire symbol
 *     symbolLayers: [{ ... }],
 *   }
 *  }
 * });
 * ```
 *
 * #### Symbol layer animations
 * Symbol layer animations are defined on the `animations` property of the symbol layer and only apply to a specific symbol layer in the symbol. All symbol layer animations are supported on [CIMVectorMarker](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMVectorMarker) and [CIMPictureMarker](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPictureMarker) symbol layers. Color and transparency animations are also supported on [CIMSolidFill](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSolidFill) and [CIMSolidStroke](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSolidStroke) symbol layers.
 *
 * ```js
 * const symbol = new CIMSymbol({
 *  data: {
 *   type: "CIMSymbolReference",
 *   symbol: {
 *     type: "CIMPointSymbol",
 *     symbolLayers: [{
 *      type: "CIMVectorMarker",
 *      enable: true,
 *      animations: [{ ... }], // animation applied to this symbol layer
 *      // other props for the symbol layer
 *     }]
 *   }
 *  }
 * });
 * ```
 *
 * > [!WARNING]
 * >
 * > **Known Limitations for CIMSymbol animations**
 * > - Animations are not currently supported in 3D [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
 * > - Animated symbols are not currently supported in the [Legend](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-legend/).
 * > - Global animations are currently only supported on [CIMPointSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPointSymbol)s.
 * > - Symbol layer animations are not fully supported within a [CIMLineSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMLineSymbol) or [CIMPolygonSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPolygonSymbol). If you use an animated marker within a line or polygon symbol, the marker placement will not be properly honored at this time. We will improve this behavior at a future release.
 *
 * ### Utility functions for working with CIMSymbol
 *
 * To get or set the values for color, rotation, and size on the CIMSymbol, use the utility functions found in `[cimSymbolUtils](https://developers.arcgis.com/javascript/latest/references/core/symbols/support/cimSymbolUtils/)`.
 *
 * The [symbolService](https://developers.arcgis.com/javascript/latest/references/core/rest/symbolService/) can be used to create a CIMSymbol from SVG.
 *
 * ![CIM symbols](https://developers.arcgis.com/javascript/latest/assets/references/core/symbols/cim/CIMSymbols.avif)
 *
 * <span id="known-limitations"></span>
 * > [!WARNING]
 * >
 * > **Known Limitations**
 * >
 * > - Not currently supported
 * >   - [CIMLineSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMLineSymbol) and [CIMPolygonSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPolygonSymbol) in 3D [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/)
 * >   - The `colorLocked` property in 3D [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/)
 * >   - The following [markerPlacements](https://github.com/Esri/cim-spec/blob/master/docs/v2/Types.md#markerplacement) on CIMMarker: `CIMMarkerPlacementAlongLineRandomSize`, `CIMMarkerPlacementAlongLineVariableSize`, and `CIMMarkerPlacementAtMeasuredUnits`.
 * >   - [CIMMeshSymbol](https://github.com/Esri/cim-spec/blob/master/docs/v2/CIMSymbols.md#cimmeshsymbol)
 * > - Limited support
 * >    - [CIMTextSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMTextSymbol) is only supported when it is embedded in a [CIMVectorMarker](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMVectorMarker) symbol layer. It is not currently supported as a standalone symbol.
 * >    - Currently, [CIMGeometricEffects](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMGeometricEffect) are not supported with [labels](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#labelingInfo).
 * > - The possible values for fontFamilyName property on [CIMTextSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMTextSymbol) are dependent upon if you working with a MapView or SceneView. See the [Labeling guide page](https://developers.arcgis.com/javascript/latest/labeling/) for detailed explanation.
 * > Unsupported fonts will fall back to `Arial Unicode MS Regular` in MapView and `sans-serif` in SceneView.
 * > - Currently, `color` property expects an array of numbers [r, g, b, a] which is different from the [CIM Specification](https://github.com/Esri/cim-spec/blob/master/docs/v2/Types.md#symbol).
 * > - Symbols with [CIMPictureMarkers](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPictureMarker), [CIMPictureStroke](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPictureStroke),
 * > or [CIMPictureFill](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPictureFill) with [geometric effects](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMGeometricEffect) are not currently supported in the [Legend](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-legend/).
 * > - Symbols with [primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPrimitiveOverride) are not currently supported in the [Legend](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-legend/).
 * > - [Primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPrimitiveOverride) on [geometric effects](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMGeometricEffect) embedded in a CIMVectorMarker symbol layer's [marker graphics](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMMarkerGraphic) are not supported at this time.
 *
 * @since 4.12
 * @see [Sample - CIMSymbol](https://developers.arcgis.com/javascript/latest/sample-code/cim-symbols/)
 * @see [Sample - CIMSymbol lines and polygons](https://developers.arcgis.com/javascript/latest/sample-code/cim-lines-and-polygons/)
 * @see [Sample - Symbol animations](https://developers.arcgis.com/javascript/latest/sample-code/cim-animations/)
 * @see [Sample - Arrows along a line](https://developers.arcgis.com/javascript/latest/sample-code/cim-line-arrows/)
 * @see [Sample - Adjust marker placement in polygon symbols](https://developers.arcgis.com/javascript/latest/sample-code/cim-marker-placement/)
 * @see [Sample - WebStyleSymbols (2D)](https://developers.arcgis.com/javascript/latest/sample-code/webstylesymbol-2d/)
 * @see [Symbol Builder](https://developers.arcgis.com/javascript/latest/symbol-builder/)
 * @see [Guide - WebStyleSymbol reference list](https://developers.arcgis.com/javascript/latest/visualization/symbols-color-ramps/esri-web-style-symbols-2d/)
 * @see [ArcGIS Blog - Create points, lines, and polygons using CIMSymbols](https://www.esri.com/arcgis-blog/products/js-api-arcgis/mapping/create-points-lines-and-polygons-using-cimsymbols/)
 * @see [ArcGIS Blog - Visualize electoral swing using composite symbols](https://www.esri.com/arcgis-blog/products/js-api-arcgis/mapping/visualize-electoral-swing-using-composite-symbols/#how-the-map-is-made)
 * @see [Presentation - ArcGIS Maps SDK for JavaScript: Dynamic Vector Symbology](https://mediaspace.esri.com/media/t/1_s9vkuyf5)
 * @see [WebStyleSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/WebStyleSymbol/)
 * @see [cimSymbolUtils](https://developers.arcgis.com/javascript/latest/references/core/symbols/support/cimSymbolUtils/)
 * @see [symbolService](https://developers.arcgis.com/javascript/latest/references/core/rest/symbolService/)
 */
export default class CIMSymbol extends Symbol {
  constructor(properties?: CIMSymbolProperties);
  /**
   * > [!WARNING]
   * >
   * > The `color` property on CIMSymbol has no effect. CIMSymbols are a reference to a symbol defined in the `data` property, and the symbol's color should be set by configuring the color on the symbol layers within the `data` property.
   * > The color property is present for consistency with other
   * > symbol types.
   *
   * @example
   * // CSS color string
   * symbol.color = "dodgerblue";
   * @example
   * // HEX string
   * symbol.color = "#33cc33";
   * @example
   * // array of RGBA values
   * symbol.color = [51, 204, 51, 0.3];
   * @example
   * // object with rgba properties
   * symbol.color = {
   *   r: 51,
   *   g: 51,
   *   b: 204,
   *   a: 0.7
   * };
   */
  accessor color: Color;
  /**
   * The JSON payload of the [CIMSymbolReference](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMSymbolReference). The CIMSymbolReference is comprised of the symbol, primitive overrides, and scale.
   *
   * **Symbol:**
   * The `symbol` property can be of type [CIMPointSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPointSymbol), [CIMLineSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMLineSymbol), or [CIMPolygonSymbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPolygonSymbol).
   * Each symbol is made up of one or more `symbolLayers`. Symbol layers are the building blocks of CIM symbols,
   * they combine to make rich graphical depictions. You can configure the shape, color, texture, size, position, etc of each symbol layer,
   * and combine multiple symbol layers to create your desired symbol. The [Symbol Builder](https://developers.arcgis.com/javascript/latest/symbol-builder/) provides a simple user interface
   * to experiment with symbol layers and their properties.
   *
   * **Primitive overrides:**
   * [Primitive overrides](https://developers.arcgis.com/javascript/latest/references/core/symbols/cim/types/#CIMPrimitiveOverride) allow you to use [Arcade expressions](https://developers.arcgis.com/javascript/latest/arcade/#visualization) to dynamically change many symbol layer properties
   * of objects,
   * each object representing a primitive override on a specific symbol layer.
   *
   * **Minimum and maximum scale:**
   * _(Since version 4.20)_
   * The `minScale` and `maxScale` values will determine the scale values at which your symbol will be visible in the view.
   * To show your symbol at all scales, these properties can either be ignored or set to 0.
   *
   * @example
   * const cimSymbol = new CIMSymbol({
   *   data: {
   *     type: "CIMSymbolReference",
   *     minScale: 750000, // only allow the symbol to be shown at certain scales
   *     maxScale: 80000,
   *     symbol: {
   *       type: "CIMLineSymbol",
   *       symbolLayers: [{ ... }]
   *     },
   *     primitiveOverrides: [{
   *       type: "CIMPrimitiveOverride",
   *       primitiveName: "symbol-layer-1", // the name of the symbol layer we want to override
   *       propertyName: "Size", // the name of the property on the symbol layer we want to override
   *       valueExpressionInfo: {
   *         type: "CIMExpressionInfo",
   *         title: "Size override",
   *         expression: "..." // the expression to change the size of the symbol
   *       }
   *     }]
   *   }
   * });
   */
  accessor data: CIMSymbolReference;
  /** The symbol type. */
  get type(): "cim";
  /**
   * Creates a deep clone of the symbol.
   *
   * @returns A deep clone of the object that
   *                                             invoked this method.
   * @example
   * // Creates a deep clone of the graphic's symbol
   * let symLyr = graphic.symbol.clone();
   */
  clone(): CIMSymbol;
}