import type { ModelParams } from "../interfaces/chart-interfaces.js";
import type { ModelTypes, SerialChartDataSortingKinds, HeatChartDataSortingKinds } from "../interfaces/common.js";
import type { SerialChartModel } from "../serial-chart-model/serial-chart-model.js";
import type { WebChartCalendarDatePartsBinning, WebChartHeatChartEmptyCell, WebChartHeatChartGradient, WebChartNullCategory } from "../../spec/web-chart.js";
import type { WebChartStatisticType, WebChartClassBreakTypes, WebChartHeatChartHeatRulesTypes, WebChartHeatChartViewTypes, WebChartLegendPositions, WebChartNullPolicyTypes, WebChartStackedKinds } from "../../spec/chart-object-literals.js";
import type { ISimpleFillSymbol, ISimpleLineSymbol } from "../../spec/rest-js-types.js";
import type { ChartConfig } from "../../utils/types/index.js";

export class HeatChartModel extends SerialChartModel {
  /** The aggregation type for the heat chart. */
  accessor aggregationType: WebChartStatisticType;
  /**
   * Bin temporal data for heat chart (not supported)
   *
   * @internal
   */
  accessor binTemporalData: boolean;
  /**
   * The number of class breaks used by the heat chart.
   *
   * @default 5
   */
  accessor breaksCount: number;
  /**
   * The classification method to be used for the heat chart.
   * `equal-interval` - Divides the range of values into equal-sized intervals.
   * `quantile` - Divides the range of values into intervals that contain an equal number of features.
   * `natural-breaks` - Identifies natural groupings of values in the data by minimizing the variance within classes and maximizing the variance between classes.
   * `manual` - Allows you to manually specify the class breaks.
   */
  accessor classificationMethod: WebChartClassBreakTypes | undefined;
  /** The heat chart's empty cell configuration. */
  accessor emptyCell: WebChartHeatChartEmptyCell | undefined;
  /** The heat chart's empty cell symbol. */
  accessor emptyCellSymbol: ISimpleFillSymbol | undefined;
  /** The heat chart's empty cell text. */
  accessor emptyCellText: string | undefined;
  /**
   * The first day of the week used for date-based bins.
   *
   * - `1`: Monday
   * - `7`: Sunday
   */
  accessor firstDayOfWeek: number | undefined;
  /**
   * Set the gradient rules for the heat chart, which define how data values map to colors.
   *
   * @example
   * In this example, we set the gradient rules for the heat chart to use a color gradient from light blue to red, with specific colors for values outside the defined range.
   *
   * ```js
   * heatChartModel.gradientRules = {
   *   colorList: [
   *     [200, 225, 255, 255],
   *     [220, 0, 0, 255],
   *   ],
   *   minValue: 100,
   *   maxValue: 250,
   *   outsideRangeLowerColor: [0, 255, 255, 255],
   *   outsideRangeUpperColor: [0, 30, 30, 255],
   * };
   * ```
   */
  accessor gradientRules: WebChartHeatChartGradient | undefined;
  /** The grid line color used by the heat chart. */
  accessor gridLineColor: number[] | undefined;
  /** The grid line width used by the heat chart. */
  accessor gridLineWidth: number | undefined;
  /**
   * The heat rules type used by the heat chart.
   * `gradient`: A gradient of colors is applied to the cells based on their values, with the range of colors determined by the minimum and maximum values in the data.
   * `renderer`: A class break renderer is used to apply specific colors to cells based on defined value ranges, allowing for more customized visualizations.
   */
  accessor heatRulesType: WebChartHeatChartHeatRulesTypes | undefined;
  /** Hide the empty rows and columns in the heat chart. */
  accessor hideEmptyRowsAndColumns: boolean | undefined;
  /** Whether to include leap day (February 29) in the heat chart when using "day of month" temporal binning. */
  accessor includeLeapDay: boolean | undefined;
  /** The heat chart's legend position. */
  accessor legendPosition: WebChartLegendPositions;
  /**
   * The null category for heat chart (not supported)
   *
   * @internal
   */
  accessor nullCategory: WebChartNullCategory;
  /**
   * The heat chart's null policy.
   * `null`: Treat null values as null.
   * `zero`: Treat null values as zero.
   */
  accessor nullPolicy: WebChartNullPolicyTypes | undefined;
  /** Heat chart only supports one numeric field, if there are multiple numeric fields provided in the array, only the first one will be used and the rest will be ignored. */
  accessor numericFields: string[];
  /**
   * The heat chart's rotatedState (not supported)
   *
   * @internal
   */
  accessor rotatedState: boolean;
  /**
   * The name of the series that is used by the heat chart.
   *
   * @internal
   */
  accessor seriesName: string | undefined;
  /**
   * Split-by field not supported for heat charts.
   *
   * @internal
   */
  accessor splitByField: string;
  /**
   * The heat chart's stacked type (not supported)
   *
   * @internal
   */
  accessor stackedType: WebChartStackedKinds | undefined;
  /**
   * The calendar view type for the heat chart.
   * `SingleCalendarView` - A single calendar view showing all data in one calendar.
   * `SequentialCalendarViews` - Multiple sequential calendar views (e.g., years).
   *
   * **Note**: This is only applicable for calendar heat charts (when `xAxisField` and `yAxisField` are date fields).
   */
  accessor viewType: WebChartHeatChartViewTypes | undefined;
  /**
   * The x axis temporal binning used by the heat chart.
   *
   * @example
   * ```ts
   * heatChartModel.xTemporalBinning = {
   *   type: WebChartTypes.CalendarDateParts,
   *   unit: WebChartCalendarDatePartsUnits.MonthOfYear,
   * };
   * ```
   */
  accessor xTemporalBinning: WebChartCalendarDatePartsBinning | undefined;
  /** The y axis field used by the heat chart. */
  accessor yAxisField: string;
  /**
   * The y axis temporal binning used by the heat chart.
   *
   * @example
   * ```ts
   * heatChartModel.yTemporalBinning = {
   *   type: WebChartTypes.CalendarDateParts,
   *   unit: WebChartCalendarDatePartsUnits.DayOfMonth,
   * };
   * ```
   */
  accessor yTemporalBinning: WebChartCalendarDatePartsBinning | undefined;
  /** Generate the proper chart title given the current config. */
  generateChartTitle(): string;
  /** Generate the proper y-axis title given the current config. */
  generateYAxisTitle(): string;
  /** Gets the grid lines symbol. Contains styling information such as line width, line style, and line color. */
  getGridLinesSymbol(): ISimpleLineSymbol | undefined;
  /** Gets the sort order for the bar chart. */
  getSortOrder(): HeatChartDataSortingKinds | SerialChartDataSortingKinds;
  /**
   * Get the sort order on the x axis for the heat chart.
   *
   * @returns {"Asc" | "Desc" | "customSort"}
   */
  getXAxisSortOrder(): HeatChartDataSortingKinds;
  /**
   * Gets the sort order for on the y axis for heat chart.
   *
   * @returns {"Asc" | "Desc" | "customSort"}
   */
  getYAxisSortOrder(): HeatChartDataSortingKinds;
  /**
   * The heat chart's second axis (not supported)
   *
   * @param _assign
   * @param _seriesIndex
   * @internal
   */
  setAssignToSecondValueAxis(_assign: boolean, _seriesIndex: number): void;
  /**
   * Sets the grid lines symbol. Contains styling information such as line width, line style, and line color.
   *
   * @param linesSymbol - The grid lines symbol.
   * @example
   * ```ts
   * heatChartModel.setGridLinesSymbol({
   *  type: "esriSLS",
   *  style: "esriSLSDash",
   *  color: [255, 100, 100, 255],
   *  width: 3,
   * });
   * ```
   */
  setGridLinesSymbol(linesSymbol: ISimpleLineSymbol | undefined): void;
  /**
   * setSortOrder is not used by heat chart; instead use setXAxisSortOrder for the x axis and setYAxisSortOrder for the y axis.
   *
   * @param _newSortOrder
   * @param _orderByList
   * @internal
   */
  setSortOrder(_newSortOrder: HeatChartDataSortingKinds | SerialChartDataSortingKinds, _orderByList?: string[]): void;
  /**
   * Completes the async setup process for the chart model. Must be called before using the model.
   *
   * @param params
   */
  setup(params: ModelParams<ChartConfig<typeof ModelTypes.HeatChart>>): Promise<void>;
  /**
   * Sets the sort order on the x axis for the heat chart.
   *
   * @param newSortOrder - The new sort order.
   * @param orderByList - The list of category's values to order by.
   */
  setXAxisSortOrder(newSortOrder: HeatChartDataSortingKinds, orderByList?: string[]): void;
  /**
   * Sets the sort order on the y axis for heat chart.
   *
   * @param newSortOrder - The new sort order.
   * @param orderByList - The list of category's values to order by.
   */
  setYAxisSortOrder(newSortOrder: HeatChartDataSortingKinds, orderByList?: string[]): void;
}