import { getLongestTextLengthFromArray } from '../../../utils/array';
import { PieLegendHoverGenerator } from '../interacting-entry-generator/pie-legend-hover-generator';
import { BaseDrawer } from './base-drawer';
/** The LegendDrawer class draws circles and text for each legend in a chart. */
export class LegendDrawer extends BaseDrawer {
  constructor() {
    super(...arguments);
    this.pieLegendHoverGenerator = new PieLegendHoverGenerator();
  }
  /**
   * This function adds interaction support to a chart by registering it with an interactor and providing a hover generator.
   *
   * @param {(SVGGElement | HTMLCanvasElement)[]} drawPiece - `drawPiece` is a parameter of type array
   * that contains either `SVGGElement` or `HTMLCanvasElement` elements. It is used as a callback
   * function to draw the legend items on the chart.
   */
  addInteractionSupport(drawPiece) {
    var _a;
    if ((_a = this.options.renderOptions.data) === null || _a === void 0 ? void 0 : _a.length) {
      this.interactor.register(this, drawPiece, this.pieLegendHoverGenerator.generate(this.options.renderOptions));
    }
  }
  /**
   * This function draws a legend on a chart using input options.
   *
   * @returns {(SVGGElement | HTMLCanvasElement)[] | undefined}  draw piece
   */
  draw() {
    const { data = [], colors, position, width } = this.options.renderOptions;
    const options = this.getChartLegendOptions(data, colors, position);
    if (options) {
      const longestLegendLength = getLongestTextLengthFromArray(data);
      return options.legends.map((legend, index) => {
        const position = this.getLegendPosition(options.position, index, longestLegendLength, width);
        return this.renderer.drawLegend(position, legend.field, legend.color, this.getStyleTextFromToken('v-font-footnote2-short'));
      });
    }
  }
  /**
   * This function takes in an array of strings and an optional position parameter, and returns an object containing legend options for a chart.
   *
   * @param {string[]} data - an array of strings representing the legend labels
   * @param {BackgroundColorsTokenType[]} [colors] - bg color token array
   * @param {ChartPosition} [position] - The `position` parameter is an optional parameter of type
   * `ChartPosition` which specifies the x and y coordinates of the chart legend on the chart. If it is
   * not provided, the default position is `{x: 10, y: 0}`.
   * @returns {ChartLegendOptions | undefined} an object of type `ChartLegendOptions`.
   */
  getChartLegendOptions(data, colors, position) {
    if (data && data.length) {
      position = position ? Object.assign({ x: 10, y: 0 }, position) : { x: 10, y: 0 };
      const legendsMap = {
        position,
        legends: data.map((text, index) => {
          return {
            field: text,
            color: this.getColorFromToken(this.getColorByIndex(index, colors)),
            icon: '',
          };
        }),
      };
      return legendsMap;
    }
  }
  /**
   * This function calculates the position of a legend on a chart based on its index and the chart layout.
   *
   * @param {ChartPosition} position - The initial position of the legend on the chart, with x and y coordinates.
   * @param {number} index - The index parameter is a number that represents the index of the legend item in the array of legends. It is used to calculate the position of the legend item on the chart.
   * @param {number} longestTextLength - text length
   * @param {number} width - chart width
   * @returns {ChartPosition} an object of type `ChartPosition` with `x` and `y` properties.
   */
  getLegendPosition(position, index, longestTextLength, width) {
    const maxWidth = width;
    if (maxWidth) {
      const restWidth = maxWidth - position.x;
      const singleWidth = longestTextLength * 7 + 24;
      const singleHeight = 18;
      const column = Math.max(Number((restWidth / singleWidth).toFixed(0)), 1);
      const row = parseInt((index / column).toString());
      const x = position.x + singleWidth * (index % column);
      const y = position.y + row * singleHeight;
      return { x, y };
    }
    return { x: 0, y: 0 };
  }
}
