import type { ChartElementLimit } from "../defaults/interfaces.js";
import type { SelectionData, ChartSubType } from "./interfaces.js";
import type { WebChartSortOrderKinds, WebChartTemporalBinningUnits, WebChartTypes, WebChartStackedKinds } from "../../spec/chart-object-literals.js";
import type { WebBoxPlot, WebChart, WebChartSeries, WebChartSeriesType } from "../../spec/web-chart.js";
import type { IField } from "../../spec/rest-js-types.js";
import type { WebChartDataItem, WebChartDataItemValue } from "../../spec/data-source.js";
import type { OverlayTerms, LegendItemVisibility } from "../../spec/events.js";

/** @internal */
export type XYChartType = typeof WebChartTypes.BarSeries | typeof WebChartTypes.BoxPlotSeries | typeof WebChartTypes.ComboLineAndBarSeries | typeof WebChartTypes.HeatSeries | typeof WebChartTypes.HistogramSeries | typeof WebChartTypes.LineSeries | typeof WebChartTypes.RadarSeries | typeof WebChartTypes.ScatterSeries;

/** @internal */
export type SerialChartType = typeof WebChartTypes.BarSeries | typeof WebChartTypes.ComboLineAndBarSeries | typeof WebChartTypes.HeatSeries | typeof WebChartTypes.LineSeries | typeof WebChartTypes.RadarSeries;

/** @internal */
export type SupportedChartType = typeof WebChartTypes.BarSeries | typeof WebChartTypes.BoxPlotSeries | typeof WebChartTypes.HeatSeries | typeof WebChartTypes.HistogramSeries | typeof WebChartTypes.LineSeries | typeof WebChartTypes.PieSeries | typeof WebChartTypes.RadarSeries | typeof WebChartTypes.ScatterSeries;

/** @internal */
export type ChartTypes = Extract<WebChartTypes, WebChartType>;

/** @internal */
export type XYChartTypes = Extract<WebChartTypes, XYChartType>;

/** @internal */
export type SerialChartTypes = Extract<WebChartTypes, SerialChartType>;

/** @internal */
export type SupportedCharts = Extract<ChartTypes, SupportedChartType>;

/**
 * Returns the color policy for the chart.  If it's not defined, `WebChartColoringPatterns.Single` will be used.
 *
 * @param chartConfig - the chart config.
 * @returns the color policy.
 * @internal
 */
export function getColorMatch(chartConfig?: WebChart): boolean;

/**
 * Indicates whether or not the chart is rotated.
 *
 * @param chartConfig - the chart config.
 * @internal
 */
export function isChartRotated(chartConfig?: WebChart): boolean;

/**
 * Getting the list of series types from a series config array.
 *
 * @param chartSeries - The array of chart's series
 * @internal
 */
export function getSeriesTypes(chartSeries?: WebChartSeries[]): ChartTypes[];

/**
 * Returns the type of stacking (side-by-side, stacked...) to be used to display the chart.
 * For Line, Bar, Box-plot, and Radar chart, default option is 'sideBySide'
 *
 * @param config
 * @internal
 */
export function getStackedType(config?: WebChart): WebChartStackedKinds | undefined;

/**
 * Escapes any single quote in the input string with a single quote for SQL.
 * For example: Cote d'Ivoire -> Cote d''Ivoire
 *
 * @param string - input string to replace for any special characters.
 * @internal
 */
export function escapeSQLString(string: string): string;

/**
 * Normalizes a string by
 *   - trimming off white spaces
 *   - if the value is a string and keepSurroundingQuotes is not true: stripping ' (single inverted comma), if present on both sides
 *   - if escape is true (or undefined): escaping special characters like ", \, /.
 * E.g.:
 * "'alpha'" => "alpha"
 * "'alpha" => No change
 * "alpha'" => No change
 * "alp'ha'" => alp''ha
 * "  'alpha'" => "alpha"
 * "alp"\/ha" => "alp\"\\\/ha"
 *
 * @param props - The string to normalize
 * @internal
 */
export function normalizeString(props: {
    value: string;
    keepSurroundingQuotes?: boolean;
    escape?: boolean;
}): string;

/**
 * Indicates whether a chart respects the number limit of elements (bars, markers, cells or slices).
 * For bar chart, different limits are set according to the number of series.
 * For line chart, a limit on the number of series and the total number of markers are set.
 * For heat chart, a limit on the number of cells is set.
 * For pie chart, a limit on the number of slices is set.
 *
 * @param props - Number total of elements on the chart
 * @internal
 */
export function isNumberOfElementsUnderLimit(props: {
    count: number;
    seriesCount: number;
    chartType?: WebChartTypes;
    chartLimits?: ChartElementLimit;
}): boolean;

/**
 * Returns the alias for the field name if it exists; otherwise return the field name itself.
 *
 * @param fields - The field name to look for in the field array
 * @param fieldName - The list of fields containing all the information regarding the fields, including the alias
 * @internal
 */
export function getFieldAlias(fields: IField[] | undefined, fieldName: string): string;

/**
 * @param fields
 * @param fieldName
 * @internal
 */
export function getFieldAlias(fields: IField[] | undefined, fieldName: undefined): undefined;

/**
 * @param fields
 * @param fieldName
 * @internal
 */
export function getFieldAlias(fields: IField[] | undefined, fieldName: string | undefined): string | undefined;

/**
 * @param fields
 * @param fieldName
 * @internal
 */
export function getFieldAlias(fields: IField[] | undefined, fieldName: string | undefined): string | undefined;

/**
 * Return the field name for the field alias if it exists; otherwise return the field alias itself.
 *
 * @param fields - The field alias to look for in the field array
 * @param fieldAlias - The list of fields containing all the information regarding the fields, including the alias
 * @internal
 */
export function getFieldNameFromFieldAlias(fields: IField[] | undefined, fieldAlias: string): string;

/**
 * Decides whether we can show the legend or not. If it returns `false`, then we should not show the legend even if `legend.visible` is `true`.
 * For Pie charts, hide the legend when there is only one slice.
 *
 * @param chartSeries
 * @internal
 */
export function canShowLegend(chartSeries: WebChartSeries[]): boolean;

/**
 * Based on a provided list of supported chart types, this function returns a boolean indicating if the config
 * contains supported series. An extra test is done for the scatterplot, pie, and histogram series.
 *
 * @param supportedChartTypes - The list of supported chart types
 * @param config - The chart's config
 * @internal
 */
export function isSupportedChart(supportedChartTypes: WebChartTypes[], config?: WebChart): boolean;

/**
 * Indicates whether a string field is empty (different from undefined, null and empty string).
 * The value is stringified before being trimmed to debunk edge cases like when the value is a numeric value.
 *
 * @param value - The value to test
 * @returns `true` if empty, `false` otherwise
 * @internal
 */
export function isEmptyStringField(value: string | null | undefined): boolean;

/**
 * Indicates whether an object contains a property key from list of properties.
 *
 * @param data - the object to look into
 * @param propertyList - the array of property keys to search the data if one of them is present.
 * @returns An object containing a boolean indicating the propertyList presence, and the property key that matched
 * @internal
 */
export function isPropertyKeyInData<T extends WebChartDataItem>(data: T, propertyList: string[]): {
    isInItem: boolean;
    expr?: string;
};

/**
 * Indicates whether an object contains the result of a calculated expression coming from a
 * query (similar to "EXPR_1").
 *
 * @param dataItem - the object to look into
 * @returns An object containing a boolean indicating the expression's presence, and the expression key that matched
 * @internal
 */
export function isQueryCalculatedExprInItem(dataItem: WebChartDataItem): {
    isInItem: boolean;
    expr?: string;
};

/**
 * Finds localized string for the given `WebChartTemporalBinningUnits` unit type.
 *
 * @param unit
 * @param strings
 * @returns Localized unit type label
 * @internal
 */
export function getTimeIntervalUnitLabel(unit: WebChartTemporalBinningUnits, strings: {
    seconds?: string;
    minutes?: string;
    hours?: string;
    days?: string;
    weeks?: string;
    months?: string;
    years?: string;
}): string;

/**
 * Returns the appropriate `index` to fetch the default color from `overlayRamp[]` array for a histogram overlay
 *
 * @param overlayType
 * @internal
 */
export function getOverlayColorIndex(overlayType: OverlayTerms | undefined): number;

/**
 * Assigns visible property to a series or an overlay
 *
 * @param event - The config that gets updated for each series visibility
 * @param config - The event that is currently being called
 * @internal
 */
export function updateSeriesVisibility(event: Pick<CustomEvent<LegendItemVisibility>, "detail">, config?: WebBoxPlot | WebChart): void;

/**
 * Sanitize an HTML string to prevent XSS attacks (https://owasp.org/www-community/attacks/xss/)
 *
 * @param inputToSanitize - The HTML string to sanitize
 * @internal
 */
export function sanitizeHTMLOutput(inputToSanitize: string): string;

/**
 * .
 * Indicates if a provided number value is valid.
 * An invalid value is: undefined | NaN | Infinite | -Infinite | null
 * See for more details:
 *   - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite
 *   - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
 *
 * @param value
 * @internal
 */
export function isValidNumber(value: WebChartDataItemValue): boolean;

/**
 * Gets the sorting field or (sorting type for box-plot) and orderBy from an input string.
 *
 * @param stringToParse - The input string to parse, like `orderByField` of a query clause or `orderDataBy` property of a chart config.
 * @param useDefault - If set to `false`, the default sort order will not be used.
 * @internal
 */
export function getOrderByComponents(stringToParse: string, useDefault?: boolean): {
    fieldToSort: string;
    orderBy?: WebChartSortOrderKinds;
};

/**
 * Gets the fields listed in the `orderByFields` property of a chart config.
 *
 * @param chartConfig - The chart config
 * @returns The list of fields to sort by
 * @internal
 */
export function getOrderByFields(chartConfig: WebChart): string[];

/**
 * Determines if certain chart subtype is a split by chart.
 *
 * @param chartSubType - The chart subtype
 * @returns `true` if the chart subtype is a split by chart, `false` otherwise
 * @internal
 */
export function isSplitByChart(chartSubType: ChartSubType): boolean;

/**
 * Util function to know if the selection data changed.
 * The selection items and selection OIDs are compared, not the selection source nor the selection indexes.
 *
 * @param selectionA - The first selection data
 * @param selectionB - The second selection data
 * @returns a boolean indicating whether the two selections are equal
 * @internal
 */
export function hasSelectionChanged(selectionA?: SelectionData, selectionB?: SelectionData): boolean;

/**
 * Indicates whether the selection data is empty.
 *
 * @param selectionData - The selection data to check
 * @internal
 */
export function isSelectionEmpty(selectionData: SelectionData | undefined): boolean;

/**
 * Sorts `arrayA` based on the indexes of the elements in `arrayB`.
 *
 * @param props - The array to be sorted
 * @internal
 */
export function sortArrayAUsingArrayB<T, K>(props?: {
    arrayA: T[];
    arrayB: T[];
    getKey: (item: T) => K;
}): T[];

/**
 * Gets the display x field for a chart subtype.
 *
 * @param chartSubType - The chart subtype.
 * @param series - The series.
 * @returns The default x field.
 * @internal
 */
export function getDisplayXField(chartSubType: ChartSubType, series?: WebChartSeriesType): string;

/**
 * Determines if an RGBA color is light or dark, considering opacity.
 *
 * @param props - Red (0-255)
 * @returns boolean
 * @internal
 */
export function isColorLight(props: {
    r: number;
    g: number;
    b: number;
    a?: number;
}): boolean;

export type WebChartType = typeof WebChartTypes.BarSeries | typeof WebChartTypes.BoxPlotSeries | typeof WebChartTypes.ComboLineAndBarSeries | typeof WebChartTypes.GaugeSeries | typeof WebChartTypes.HeatSeries | typeof WebChartTypes.HistogramSeries | typeof WebChartTypes.LineSeries | typeof WebChartTypes.PieSeries | typeof WebChartTypes.RadarSeries | typeof WebChartTypes.ScatterSeries;