/**
 * This module contains Accessor [TypeScript](https://www.typescriptlang.org/docs/handbook/decorators.html)
 * decorators. Decorators allow us to define and/or modify behavior of existing properties, methods,
 * and constructors at design time.
 *
 * @since 4.2
 * @see [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/)
 * @see [widget](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/widget/)
 * @see [Get started - TypeScript](https://developers.arcgis.com/javascript/latest/get-started/#typescript)
 * @see [Implementing Accessor](https://developers.arcgis.com/javascript/latest/implementing-accessor/)
 */
import type { InputPropertyMetadata } from "./types.js";

/**
 * A property decorator that creates a two-way binding between the property it decorates and an inner property of one
 * of its members.
 *
 * @deprecated since version 5.0. Create a getter instead.
 * @param aliasedPropertyName - The aliased property name.
 * @returns The property decorator.
 * @example
 * // property example
 * \@aliasOf("viewModel.name")
 * name: string = "name";
 * @example
 * // method example
 * \@aliasOf("viewModel.someMethod")
 * someMethod: () => string;
 */
export function aliasOf(aliasedPropertyName: string): PropertyDecorator;

/**
 * This convenience decorator is used to define an [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/) property.
 * Any property defined with this decorator can now be `get` and `set`. In addition,
 * you can [watch for any property changes](https://developers.arcgis.com/javascript/latest/watch-for-changes/#watch-for-changes-in-the-api).
 *
 * @param metadata - An object describing the property.
 * @returns The property descriptor.
 * @see [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/)
 * @example
 * // typescript syntax to specify the property.
 * \@property()
 * title: string = "Awesome Title!"
 */
export function property<T extends Base, Base = T>(metadata?: InputPropertyMetadata<T, Base>): PropertyDecorator;

/**
 * This decorator is used to define an [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/) subclass. Any subclass
 * of [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/) must use the `@subclass` decorator.
 *
 * @param declaredClass - The subclass name.
 * @returns The class decorator.
 * @example
 * // TypeScript syntax which creates a subclass that extends the Accessor class.
 * \@subclass("my.custom.class")
 * class MyCustomClass extends Accessor {
 *   // ...
 * }
 */
export function subclass(declaredClass?: string): any;

/**
 * This property decorator is used to define the function or class for a property.
 *
 * @param functionOrClass - The function or class to cast the property
 * @returns The property descriptor.
 * @see [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/)
 * @example
 * import Accessor from "@arcgis/core/core/Accessor.js";
 * import { subclass, property, cast } from "@arcgis/core/core/accessorSupport/decorators.js";
 *
 * function clampRGB(component: number) {
 *   return Math.min(Math.max(component, 0), 255);
 * }
 *
 * function clampAlpha(alpha: number) {
 *   return Math.min(Math.max(alpha, 0), 1);
 * }
 *
 * \@subclass()
 * class Color extends Accessor {
 *
 *   \@property()
 *   \@cast(clampRGB)
 *   r: number = 0;
 *
 *   \@property()
 *   \@cast(clampRGB)
 *   g: number = 0;
 *
 *   \@property()
 *   \@cast(clampRGB)
 *   b: number = 0;
 *
 *   \@property()
 *   \@cast(clampRGB)
 *   a: number = 1;
 * }
 */
export function cast(functionOrClass: Function): PropertyDecorator;

/**
 * This method decorator is used to define the method that will cast a property from a class.
 *
 * @param propertyName - The property name the function will cast.
 * @returns The method descriptor.
 * @see [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/)
 * @example
 * import Accessor from "@arcgis/core/core/Accessor.js";
 * import { subclass, property, cast } from "@arcgis/core/core/accessorSupport/decorators.js";
 *
 * \@subclass()
 * class Color extends Accessor {
 *
 *   \@property()
 *   r: number = 0;
 *
 *   \@property()
 *   g: number = 0;
 *
 *   \@property()
 *   b: number = 0;
 *
 *   \@property()
 *   a: number = 1;
 *
 *   \@cast("r")
 *   \@cast("g")
 *   \@cast("b")
 *   protected castComponent(value) {
 *     // cast method that clamp the value that
 *     // will be set on r, g or b between 0 and 255
 *     return Math.max(0, Math.min(255, value));
 *   }
 *
 *   \@cast("a")
 *   protected castAlpha(value) {
 *     // cast method that clamp the value that
 *     // will be set on a between 0 and 255
 *     return Math.max(0, Math.min(1, value));
 *   }
 * }
 */
export function cast(propertyName: string): MethodDecorator;