import type Graphic from "../../../Graphic.js";
import type CSVLayer from "../../../layers/CSVLayer.js";
import type FeatureLayer from "../../../layers/FeatureLayer.js";
import type GeoJSONLayer from "../../../layers/GeoJSONLayer.js";
import type ImageryLayer from "../../../layers/ImageryLayer.js";
import type OrientedImageryLayer from "../../../layers/OrientedImageryLayer.js";
import type ParquetLayer from "../../../layers/ParquetLayer.js";
import type SceneLayer from "../../../layers/SceneLayer.js";
import type WFSLayer from "../../../layers/WFSLayer.js";
import type CatalogFootprintLayer from "../../../layers/catalog/CatalogFootprintLayer.js";
import type KnowledgeGraphSublayer from "../../../layers/knowledgeGraph/KnowledgeGraphSublayer.js";
import type Field from "../../../layers/support/Field.js";
import type Sublayer from "../../../layers/support/Sublayer.js";
import type AttachmentInfo from "../../../rest/query/support/AttachmentInfo.js";
import type Column from "../Grid/Column.js";
import type AttachmentsColumnTemplate from "./AttachmentsColumnTemplate.js";
import type ColumnTemplate from "./ColumnTemplate.js";
import type FieldColumnTemplate from "./FieldColumnTemplate.js";
import type GroupColumnTemplate from "./GroupColumnTemplate.js";
import type RelationshipColumnTemplate from "./RelationshipColumnTemplate.js";
import type { Icon } from "@esri/calcite-components/components/calcite-icon";
import type { GeometryUnion } from "../../../geometry/types.js";
import type { FieldValue } from "../../../layers/support/fieldUtils.js";
import type { ObjectId } from "../../../views/types.js";
import type { CellValue, Direction } from "../Grid/types.js";

/** @since 5.0 */
export interface FieldValueFormatFunctionParameters extends FormatFunctionParameters {}

/** @since 5.0 */
export interface FormatFunctionParameters {
  /**
   * _(Since 4.31)_ A reference to attachments for the associated feature.
   *
   * @since 5.0
   */
  attachments?: AttachmentInfo[] | null;
  /**
   * A reference to this specific Column.
   *
   * @since 5.0
   */
  column: Column;
  /**
   * A reference to the feature represented by the associated row.
   *
   * @since 5.0
   */
  feature: Graphic;
  /**
   * Index of the associated row being rendered.
   *
   * @since 5.0
   */
  index: number;
  /**
   * _(Since 4.31)_ Virtual index of the associated row being rendered. Unlike `index`, a row's `virtualIndex` changes as the table scrolls. The first row in the DOM has a `virtualIndex` of 0. As rows are added/removed from the DOM, the virtual index adjusts before it renders. This can help with performance when rendering large datasets.
   *
   * @since 5.0
   */
  virtualIndex: number;
  /**
   * _(Since 4.31)_ A reference to related records for the associated feature.
   *
   * @since 5.0
   */
  relatedRecords?: RelatedRecordInfo[] | null;
  /**
   * Current projected value of the cell.
   *
   * @since 5.0
   */
  value: CellValue;
  /**
   * The field associated with the column.
   *
   * @since 5.0
   */
  field?: Field | null;
}

/** @since 5.0 */
export type FeatureTableSupportedLayer = CatalogFootprintLayer | CSVLayer | FeatureLayer | GeoJSONLayer | ImageryLayer | KnowledgeGraphSublayer | SceneLayer | WFSLayer | OrientedImageryLayer | ParquetLayer | Sublayer;

/** @since 5.0 */
export type FeatureTableSupportedColumn = Column;

/**
 * Custom function for rendering cell content. Accepts a string, number, an HTML element or equivalent node type (e.g. a [Calcite component](https://developers.arcgis.com/calcite-design-system/components/)).
 *
 * @param params - An object containing information about the associated row and feature.
 * @returns Formatted content to be displayed in the cell.
 * @since 5.0
 */
export type FormatFunction = (params: FormatFunctionParameters) => CellValue | HTMLElement;

/**
 * Custom function for rendering cell content. Accepts a string, number, an HTML element or equivalent node type (e.g. a [Calcite component](https://developers.arcgis.com/calcite-design-system/components/)).
 *
 * @param params - An object containing information about the associated row and feature.
 * @returns Formatted content to be displayed in the cell.
 * @since 5.0
 */
export type FieldValueFormatFunction = (params: FieldValueFormatFunctionParameters) => FieldValue | HTMLElement;

/**
 * Information about an item in the store, used to represent a row in the table.
 *
 * @since 5.0
 */
export interface FeatureStoreItem {
  /**
   * The object ID of the feature represented by the item.
   *
   * @since 5.0
   */
  objectId: ObjectId;
  /**
   * The feature represented by the item.
   *
   * @since 5.0
   */
  feature: Graphic;
  /**
   * The attachment information for the associated feature.
   *
   * @since 5.0
   */
  attachments?: AttachmentInfo[] | null;
  /**
   * The related record information for the associated feature.
   *
   * @since 5.0
   */
  relatedRecords?: RelatedRecordInfo[] | null;
}

/** @since 5.0 */
export type FeatureTableSupportedFilters = GeometryFilter | SelectionFilter;

/**
 * Use this for spatial filtering, it is the [Geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Geometry.html) used to filter out data within the table.
 *
 * @since 5.0
 * @see [FeatureTableViewModel.filterGeometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-FeatureTableViewModel.html#filterGeometry)
 * @see [FeatureTableViewModel.activeFilters](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-FeatureTableViewModel.html#activeFilters)
 * @see [Sample - FeatureTable using a map](https://developers.arcgis.com/javascript/latest/sample-code/widgets-featuretable-map/)
 */
export interface GeometryFilter extends TableFilter {
  /**
   * The type of the filter used. This will always read as `"geometry"`.
   *
   * @since 5.0
   */
  type: "geometry";
  /**
   * The geometry used to filter out the table's data.
   *
   * @since 5.0
   */
  geometry: GeometryUnion;
}

/**
 * Use this for selecting rows within the table based off of their object ID.
 *
 * @since 5.0
 * @see [FeatureTableViewModel.filterBySelection()](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-FeatureTableViewModel.html#filterBySelection)
 * @see [FeatureTableViewModel.activeFilters](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-FeatureTableViewModel.html#activeFilters)
 */
export interface SelectionFilter extends TableFilter {
  /**
   * The type of the filter used. This will always read as `"selection"`.
   *
   * @since 5.0
   */
  type: "selection";
  /**
   * An array of numbers indicating the row's object IDs.
   *
   * @since 5.0
   */
  objectIds: ObjectId[];
}

/** @since 5.0 */
export interface TableFilter {
  /**
   * The type of the filter used.
   *
   * @since 5.0
   */
  type: string;
}

/**
 * An array of objects containing a column's name and sort direction. This is used in conjunction with [FeatureTableViewModel.activeSortOrders](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-FeatureTableViewModel.html#activeSortOrders) to help retain a column's sort order while querying.
 *
 * @since 5.0
 * @see [FeatureTableViewModel.activeSortOrders](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-FeatureTableViewModel.html#activeSortOrders)
 */
export interface ColumnSortOrder {
  /**
   * The field name as defined by the layer. Set this property to indicate which column to sort. This should match the field name as defined at the feature service level.
   *
   * @since 5.0
   */
  fieldName: string;
  /**
   * Controls the sort order of the column given the set `fieldName`.
   *
   * Possible Value | Description
   * ---------------|------------
   * asc | Sorts the column in ascending order.
   * desc | Sorts the column in descending order.
   * null | No sort is applied to the column.
   *
   * @since 5.0
   */
  direction: Direction;
}

/** @since 5.0 */
export interface ActionColumnCallbackParameters {
  /**
   * The index of the associated row.
   *
   * @since 5.0
   */
  index: number;
  /**
   * A reference to the associated feature.
   *
   * @since 5.0
   */
  feature: Graphic;
  /**
   * A reference to the interaction event.
   *
   * @since 5.0
   */
  native: MouseEvent | KeyboardEvent;
}

/**
 * Function called when an action is clicked or pressed.
 *
 * @param params - An object containing information about the associated row and feature.
 * @since 5.0
 */
export type ActionColumnCallback = (params: ActionColumnCallbackParameters) => void;

/**
 * Configuration for the [FeatureTable's actionColumn](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#actionColumn).
 *
 * @since 5.0
 * @example
 * // The following snippet demonstrates how to configure an action column that adds a button to each row which allows the user to zoom to the associated row's feature within the view.
 * featureTable.viewModel.actionColumnConfig = {
 *   label: "Go to feature",
 *    icon: "zoom-to-object",
 *    callback: (params) => {
 *     view.goTo(params.feature);
 *  }
 * }
 */
export interface ActionColumnConfig {
  /**
   * The accessible label to display when hovering over the action.
   *
   * @since 5.0
   */
  label: string;
  /**
   * Callback function invoked when the action is clicked or activated via the keyboard.
   *
   * @since 5.0
   */
  callback: ActionColumnCallback;
  /**
   * Indicates if a specific action should be conditionally disabled.
   *
   * @since 5.0
   */
  disabled?: ActionColumnDisabledFunction | boolean;
  /**
   * Indicates the column should be frozen to the end of the table.
   *
   * @since 5.0
   */
  frozenToEnd?: boolean;
  /**
   * The string value indicating the [Calcite icon](https://developers.arcgis.com/calcite-design-system/icons/) displayed for the action.
   *
   * @since 5.0
   */
  icon?: Icon["icon"];
}

/** @since 5.0 */
export interface ActionColumnDisabledParameters {
  /**
   * The feature to use when determining if the action should be disabled.
   *
   * @since 5.0
   */
  feature: Graphic;
  /**
   * The row's index position when determining if the action should be disabled.
   *
   * @since 5.0
   */
  index: number;
}

/**
 * The function that is called when determining if an action should be disabled.
 *
 * @param params - An object containing information about an associated row and feature.
 * @returns Indicates whether the action should be disabled.
 * @since 5.0
 */
export type ActionColumnDisabledFunction = (params: ActionColumnDisabledParameters) => boolean;

/**
 * The related records for the associated feature used in the [Columns's](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-Grid-Column.html#formatFunction) and [FieldColumn's](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable-support-types.html#FieldValueFormatFunction) `formatFunction`.
 *
 * @since 5.0
 */
export interface RelatedRecordInfo {
  /**
   * The ID of the relationship defined in the data source.
   *
   * @since 5.0
   */
  relationshipId: number;
  /**
   * The number of related records associated with the feature.
   *
   * @since 5.0
   */
  count: number;
}

/** @since 5.0 */
export type SupportedColumnTemplates = ColumnTemplate | FieldColumnTemplate | GroupColumnTemplate | AttachmentsColumnTemplate | RelationshipColumnTemplate;

/** @since 5.0 */
export type GroupColumnSupportedTemplates = Exclude<SupportedColumnTemplates, GroupColumnTemplate>;