/* eslint-disable jsdoc/require-param-type, jsdoc/require-returns-type, jsdoc/require-param, jsdoc/require-returns */
/**
 * D3 Shape Polyfill - Lightweight SVG shape generators.
 *
 * This is a drop-in replacement for d3-shape, implementing only the methods
 * used in the Vega chart rendering system: line, arc, and pie.
 *
 * @see VD-5022 - [Zero Dependencies] remove d3 dependency
 */
/**
 * A line generator that creates SVG path data strings from data arrays.
 * Mimics d3.line() with .x() and .y() value extractors.
 */
class LineGenerator {
  constructor() {
    /** Default x value extractor: reads `.x` property or first array index. */
    this.xAccessor = (d) => { var _a; return (_a = d.x) !== null && _a !== void 0 ? _a : d[0]; };
    /** Default y value extractor: reads `.y` property or second array index. */
    this.yAccessor = (d) => { var _a; return (_a = d.y) !== null && _a !== void 0 ? _a : d[1]; };
  }
  /**
   * Sets the x accessor function.
   *
   * @param accessor - Function that returns the x value for a datum.
   * @returns This generator for chaining.
   */
  x(accessor) {
    this.xAccessor = accessor;
    return this;
  }
  /**
   * Sets the y accessor function.
   *
   * @param accessor - Function that returns the y value for a datum.
   * @returns This generator for chaining.
   */
  y(accessor) {
    this.yAccessor = accessor;
    return this;
  }
  /**
   * Generates an SVG path data string for the given data.
   * Called as a function (used by d3's attr('d', lineGenerator)).
   *
   * @param data - Array of data points.
   * @returns SVG path data string (M...L...L...).
   */
  generate(data) {
    if (!data || data.length === 0) {
      return '';
    }
    const parts = [];
    for (let i = 0; i < data.length; i++) {
      const xVal = this.xAccessor(data[i], i);
      const yVal = this.yAccessor(data[i], i);
      parts.push(i === 0 ? `M${xVal},${yVal}` : `L${xVal},${yVal}`);
    }
    return parts.join('');
  }
}
/**
 * Creates a line generator. Mimics d3.line<T>().
 * The returned object is also callable as a function for d3 compatibility.
 *
 * @returns A new LineGenerator with callable function interface.
 */
export function line() {
  const generator = new LineGenerator();
  /* eslint-disable jsdoc/require-jsdoc */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const fn = (data) => generator.generate(data);
  fn.x = (accessor) => {
    generator.x(accessor);
    return fn;
  };
  fn.y = (accessor) => {
    generator.y(accessor);
    return fn;
  };
  fn.generate = (data) => generator.generate(data);
  /* eslint-enable jsdoc/require-jsdoc */
  return fn;
}
// ─── Arc Generator ──────────────────────────────────────────────────
/**
 * An arc generator that creates SVG path data strings for arc/pie slices.
 * Mimics d3.arc<T>() with .innerRadius() and .outerRadius() value setters.
 */
class ArcGenerator {
  constructor() {
    /** Inner radius value for the arc. */
    this.innerRadiusValue = 0;
    /** Outer radius value for the arc. */
    this.outerRadiusValue = 0;
  }
  /**
   * Sets the inner radius for the arc.
   *
   * @param radius - Inner radius value.
   * @returns This generator for chaining.
   */
  innerRadius(radius) {
    this.innerRadiusValue = radius;
    return this;
  }
  /**
   * Sets the outer radius for the arc.
   *
   * @param radius - Outer radius value.
   * @returns This generator for chaining.
   */
  outerRadius(radius) {
    this.outerRadiusValue = radius;
    return this;
  }
  /**
   * Generates an SVG path data string for an arc datum.
   * The datum must have startAngle and endAngle properties (in angle units).
   *
   * @param d - Arc datum with startAngle and endAngle.
   * @returns SVG path data string for the arc.
   */
  generate(d) {
    const datum = d;
    const startAngle = datum.startAngle - Math.PI / 2;
    const endAngle = datum.endAngle - Math.PI / 2;
    const innerR = this.innerRadiusValue;
    const outerR = this.outerRadiusValue;
    const angleDiff = endAngle - startAngle;
    const largeArcFlag = Math.abs(angleDiff) >= Math.PI ? 1 : 0;
    // Outer arc endpoints
    const outerStartX = outerR * Math.cos(startAngle);
    const outerStartY = outerR * Math.sin(startAngle);
    const outerEndX = outerR * Math.cos(endAngle);
    const outerEndY = outerR * Math.sin(endAngle);
    if (innerR > 0) {
      // Donut arc: outer arc clockwise + inner arc counter-clockwise
      const innerEndX = innerR * Math.cos(endAngle);
      const innerEndY = innerR * Math.sin(endAngle);
      const innerStartX = innerR * Math.cos(startAngle);
      const innerStartY = innerR * Math.sin(startAngle);
      return [
        `M${outerStartX},${outerStartY}`,
        `A${outerR},${outerR},0,${largeArcFlag},1,${outerEndX},${outerEndY}`,
        `L${innerEndX},${innerEndY}`,
        `A${innerR},${innerR},0,${largeArcFlag},0,${innerStartX},${innerStartY}`,
        'Z',
      ].join('');
    }
    else {
      // Pie arc: start at outer edge, arc, line to center, close
      return [
        `M${outerStartX},${outerStartY}`,
        `A${outerR},${outerR},0,${largeArcFlag},1,${outerEndX},${outerEndY}`,
        'L0,0',
        'Z',
      ].join('');
    }
  }
}
/**
 * Creates an arc generator. Mimics d3.arc<T>().
 * The returned object is also callable as a function for d3 compatibility.
 *
 * @returns A new ArcGenerator with callable function interface.
 */
export function arc() {
  const generator = new ArcGenerator();
  /* eslint-disable jsdoc/require-jsdoc */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const fn = (d) => generator.generate(d);
  fn.innerRadius = (radius) => {
    generator.innerRadius(radius);
    return fn;
  };
  fn.outerRadius = (radius) => {
    generator.outerRadius(radius);
    return fn;
  };
  fn.generate = (d) => generator.generate(d);
  /* eslint-enable jsdoc/require-jsdoc */
  return fn;
}
/**
 * A pie layout generator that computes start/end angles for data items.
 * Mimics d3.pie<T>() with .value() setter.
 */
class PieGenerator {
  constructor() {
    /** Default value extractor: reads `.value` property or falls back to 0. */
    this.valueAccessor = (d) => { var _a; return (_a = d.value) !== null && _a !== void 0 ? _a : 0; };
  }
  /**
   * Sets the value accessor function.
   *
   * @param accessor - Function that returns the numeric value for each datum.
   * @returns This generator for chaining.
   */
  value(accessor) {
    this.valueAccessor = accessor;
    return this;
  }
  /**
   * Computes pie arc data from the input data array.
   *
   * @param data - Array of data items.
   * @returns Array of PieArcDatum with computed angles.
   */
  generate(data) {
    const values = data.map((d) => this.valueAccessor(d));
    const total = values.reduce((sum, v) => sum + v, 0);
    const n = data.length;
    // Sort indices by descending value (d3.pie default sort)
    const indices = Array.from({ length: n }, (_, i) => i);
    indices.sort((a, b) => values[b] - values[a]);
    // Assign angles in sorted order, place arcs at original indices
    const arcs = new Array(n);
    let currentAngle = 0;
    for (const index of indices) {
      const angle = total > 0 ? (values[index] / total) * 2 * Math.PI : 0;
      arcs[index] = {
        data: data[index],
        index: index,
        value: values[index],
        startAngle: currentAngle,
        endAngle: currentAngle + angle,
        padAngle: 0,
      };
      currentAngle += angle;
    }
    return arcs;
  }
}
/**
 * Creates a pie layout generator. Mimics d3.pie<T>().
 * The returned object is also callable as a function for d3 compatibility.
 *
 * @returns A new PieGenerator with callable function interface.
 */
export function pie() {
  const generator = new PieGenerator();
  /* eslint-disable jsdoc/require-jsdoc */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const fn = (data) => generator.generate(data);
  fn.value = (accessor) => {
    generator.value(accessor);
    return fn;
  };
  fn.generate = (data) => generator.generate(data);
  /* eslint-enable jsdoc/require-jsdoc */
  return fn;
}
