import { flatNestedArray } from '../../../utils/array';
import { scaleTime, scaleLinear, scaleBand, extent as d3Extent } from '../../../polyfill/d3';
/** The XAxisInputProcessor class generates X-axis options for a line chart based on input data and previous layout results. */
export class XAxisInputProcessor {
  /**
   * This function generates X-axis options for a line chart based on input data and previous layout results.
   *
   * @param {ChartOptions<LineChartDataType>} input - An object containing chart options, including the data source, x-axis options, and
   * container element.
   * @param {LayoutProcessResultType} [previousOutput] - The optional output from the previous layout
   * process. It is of type LayoutProcessResultType and contains information about the innerWidth and
   * innerHeight of the chart container.
   * @returns {ChartExtend<AxisScale<AxisDomain>>} a ChartExtend object that contains the options for the X-axis of a line chart, including
   * the scale generated by the scaleGenerator and the axis options generated by the axisGenerator.
   */
  process(input, previousOutput) {
    const { dataSource, xAxis, container } = input;
    const { innerWidth, innerHeight } = previousOutput;
    const xAxisType = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.type) || 'value';
    const scale = this.getScale(dataSource, innerWidth, xAxisType, container.tagName === 'VEGA-LINE-CHART' ? 1 : 0.1, xAxis === null || xAxis === void 0 ? void 0 : xAxis.sorter);
    return {
      start: { x: 0, y: innerHeight },
      end: { x: innerWidth, y: innerHeight },
      tickSize: 4,
      scale: scale,
      labelFormatter: xAxis === null || xAxis === void 0 ? void 0 : xAxis.labelFormatter,
      width: innerWidth,
      height: innerHeight,
    };
  }
  /**
   * get x scale
   *
   * @param {ChartDataSourceItem[]} data data source
   * @param {number} width svg width
   * @param {ChartXAxisType} xAxisType x axis data type
   * @param {number} padding x position offset value
   * @param {(item:string,nextItem:string)=>number} sorter the sorter function using when the category type
   * @returns {AxisScale<AxisDomain>} x scale
   */
  getScale(data, width, xAxisType, padding = 0.1, sorter) {
    const flatData = flatNestedArray(data);
    const xData = flatData.map((item) => item.x);
    let xScale;
    if (xAxisType === 'time') {
      const ext = d3Extent(xData);
      xScale = scaleTime()
        .domain(ext[0] !== undefined ? ext : [new Date(), new Date()])
        .range([0, width]);
    }
    else if (xAxisType === 'category') {
      xScale = scaleBand(typeof sorter === 'function' ? xData.sort(sorter) : xData, [0, width]).padding(padding);
    }
    else {
      const ext = d3Extent(xData);
      xScale = scaleLinear()
        .domain(ext[0] !== undefined ? ext : [0, 0])
        .range([0, width]);
    }
    return xScale;
  }
}
