import type { Icon } from "@esri/calcite-components/components/calcite-icon";
import type { EventedAccessor } from "../core/Evented.js";
import type { EsriPromiseMixin } from "../core/Promise.js";

export interface WidgetProperties<Properties extends WidgetProperties = any> extends Partial<Pick<Widget<Properties>, "icon" | "id" | "label" | "topLayerDisabled" | "visible">> {
  /**
   * The ID or node representing the DOM element containing the widget.
   * This property can only be set once. The following examples are all valid use case when working with widgets.
   *
   * @example
   * // Create the HTML div element programmatically at runtime and set to the widget's container
   * const basemapGallery = new BasemapGallery({
   *   view: view,
   *   container: document.createElement("div")
   * });
   *
   * // Add the widget to the top-right corner of the view
   * view.ui.add(basemapGallery, {
   *   position: "top-right"
   * });
   * @example
   * // Specify an already-defined HTML div element in the widget's container
   *
   * const basemapGallery = new BasemapGallery({
   *   view: view,
   *   container: basemapGalleryDiv
   * });
   *
   * // Add the widget to the top-right corner of the view
   * view.ui.add(basemapGallery, {
   *   position: "top-right"
   * });
   *
   * // HTML markup
   * <body>
   *   <div id="viewDiv"></div>
   *   <div id="basemapGalleryDiv"></div>
   * </body>
   * @example
   * // Specify the widget while adding to the view's UI
   * const basemapGallery = new BasemapGallery({
   *   view: view
   * });
   *
   * // Add the widget to the top-right corner of the view
   * view.ui.add(basemapGallery, {
   *   position: "top-right"
   * });
   */
  container?: HTMLElement | string | null;
}

/**
 * The base class for the SDK's out-of-the-box widgets. Each widget's presentation is separate from its properties, methods, and data.
 *
 * The properties and methods of each widget are handled in its `viewModel` property, which is an
 * [Accessor](https://developers.arcgis.com/javascript/latest/references/core/core/Accessor/)-based class. Since each view model class extends Accessor,
 * all properties on the widget can be accessed using the methods outlined in the
 * [Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern) guide topic.
 *
 * @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 [Guide - Implementing Accessor](https://developers.arcgis.com/javascript/latest/implementing-accessor/)
 * @see [Guide - Watching for changes](https://developers.arcgis.com/javascript/latest/watch-for-changes/#watch-for-changes-in-the-api)
 * @see [Guide - Watching for component changes](https://developers.arcgis.com/javascript/latest/watch-for-changes/#watch-for-changes-in-web-components)
 * @see [Guide - Get started: TypeScript](https://developers.arcgis.com/javascript/latest/get-started/#typescript)
 */
export default abstract class Widget<Properties extends WidgetProperties = any> extends WidgetSuperclass {
  /**
   * The ID or node representing the DOM element containing the widget.
   * This property can only be set once. The following examples are all valid use case when working with widgets.
   *
   * @example
   * // Create the HTML div element programmatically at runtime and set to the widget's container
   * const basemapGallery = new BasemapGallery({
   *   view: view,
   *   container: document.createElement("div")
   * });
   *
   * // Add the widget to the top-right corner of the view
   * view.ui.add(basemapGallery, {
   *   position: "top-right"
   * });
   * @example
   * // Specify an already-defined HTML div element in the widget's container
   *
   * const basemapGallery = new BasemapGallery({
   *   view: view,
   *   container: basemapGalleryDiv
   * });
   *
   * // Add the widget to the top-right corner of the view
   * view.ui.add(basemapGallery, {
   *   position: "top-right"
   * });
   *
   * // HTML markup
   * <body>
   *   <div id="viewDiv"></div>
   *   <div id="basemapGalleryDiv"></div>
   * </body>
   * @example
   * // Specify the widget while adding to the view's UI
   * const basemapGallery = new BasemapGallery({
   *   view: view
   * });
   *
   * // Add the widget to the top-right corner of the view
   * view.ui.add(basemapGallery, {
   *   position: "top-right"
   * });
   */
  get container(): HTMLElement | null | undefined;
  set container(value: HTMLElement | string | null | undefined);
  /** When `true`, this property indicates whether the widget has been destroyed. */
  get destroyed(): boolean;
  /**
   * Icon which represents the widget. It is typically used when the widget is controlled by another
   * one (e.g. in the Expand widget).
   *
   * @since 4.27
   * @see [Calcite Icon Search](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  accessor icon: Icon["icon"] | null | undefined;
  /**
   * The unique ID assigned to the widget when the widget is created.
   * If not set by the developer, it will default to the container ID,
   * or if that is not present then it will be automatically generated.
   */
  accessor id: string;
  /**
   * The widget's label.
   *
   * This property is useful whenever the widget is controlled by another one (e.g. [Expand](https://developers.arcgis.com/javascript/latest/references/core/widgets/Expand/))
   *
   * @since 4.11
   */
  accessor label: string | null | undefined;
  /**
   * @default false
   * @internal
   */
  accessor topLayerDisabled: boolean;
  /**
   * Indicates whether the widget is visible.
   *
   * If `false`, the widget will no longer be rendered in the web document. This may affect the layout of other elements or widgets in the document. For example, if this widget is
   * the first of three widgets associated to the upper right hand corner of the [DefaultUI](https://developers.arcgis.com/javascript/latest/references/core/views/ui/DefaultUI/), then the other widgets will reposition when this widget is made invisible.
   * For more information, refer to the css [display](https://developer.mozilla.org/en-US/docs/Web/CSS/display) value of `"none"`.
   *
   * @default true
   * @example
   * // Hides the widget in the view
   * widget.visible = false;
   */
  accessor visible: boolean;
  /**
   * A utility method used for building the value for a widget's `class` property.
   * This aids in simplifying css class setup.
   *
   * @param classNames - The class names.
   * @returns The computed class name.
   * @since 4.7
   * @example
   * // .tsx syntax showing how to set css classes while rendering the widget
   *
   * render() {
   *   const dynamicClasses = {
   *     [css.flip]: this.flip,
   *     [css.primary]: this.primary
   *   };
   *
   *   return (
   *     <div class={classes(css.root, css.mixin, dynamicClasses)} />
   *   );
   * }
   */
  classes(...classNames: ((string | null | undefined) | ((string[] | Record<string, boolean>) | null | undefined) | false | null | undefined)[]): string;
  /** Destroys the widget instance. */
  destroy(): void;
  /** Executes after widget is ready for rendering. */
  postInitialize(): void;
  /**
   * This method is implemented by subclasses for rendering.
   *
   * @returns The rendered virtual node.
   */
  render(): any | null;
  /** Renders widget to the DOM immediately. */
  renderNow(): void;
  /** Schedules widget rendering. This method is useful for changes affecting the UI. */
  scheduleRender(): void;
}
declare const WidgetSuperclass: typeof EventedAccessor & typeof EsriPromiseMixin