import React from 'react';
import { G, Line } from 'react-native-svg';
import { colors } from '../../styles';
import { ScaleBandType, ScaleLinearType } from './graph-types';

interface CustomGridProps {
  x: ScaleBandType;
  y: ScaleLinearType;
  ticks: Array<number>;
  includeVertical?: boolean;
  xTicks?: Array<number | string>;
}
/**
 * CustomGrid Component
 * 
 * This component is used within a react-native-svg-chart component to render grid lines.
 * 
 * @param {ScaleBandType} x - X-axis scale function, received from the parent chart component.
 * @param {ScaleLinearType} y - Y-axis scale function, received from the parent chart component.
 * @param {Array<number>} ticks - Y-axis tick values for horizontal lines, received from the parent.
 * @param {boolean} [includeVertical=false] - Enables experimental vertical grid lines.
 * @param {Array<number|string>} [xTicks] - X-axis tick values for vertical lines, necessary if `includeVertical` is true.
 *
 * Behavior:
 *  - Renders horizontal grid lines based on the `ticks` & scale functions provided by the parent chart component.
 *  - Vertical grid lines are experimental and can be enabled with `includeVertical` set to true.
 *    However, their scaling and positioning may not be accurate relative to XAxis component (if used).
 *
 * Usage:
 *  <Chart ... >
 *    <CustomGrid />
 *  </Chart>
 *
 * Note: Use `includeVertical` cautiously; vertical lines are not fully developed.
 */
export const CustomGrid: React.FC<Partial<CustomGridProps>> = ({
  x,
  y,
  ticks,
  xTicks,
  includeVertical = false
}) => {
  const [firstTick, ...remainingTicks] = ticks;
  const dashArray = [1, 3];
  const strokeSolidWidth = 0.2;
  const strokeSolidColor = colors.bgBlack;
  const strokeDashWidth = 1;
  const strokeDashColor = colors.lightGrey;

  const renderHorizontalLine = (tick: number, stroke: string, strokeWidth: number, dashArray?: number[]) => (
    <Line
      key={`line-${tick}`}
      x1="0%"
      x2="100%"
      y1={y(tick)}
      y2={y(tick)}
      stroke={stroke}
      strokeWidth={strokeWidth}
      strokeDasharray={dashArray}
    />
  );

  const topY = y(Math.max(...ticks));
  const bottomY = y(Math.min(...ticks));
  const renderVerticalLine = (tick: number, stroke: string, strokeWidth: number, dashArray?: number[]) => {
    return (
      <Line
        key={`vertical-line-${tick}`}
        x1={x(tick)}
        x2={x(tick)}
        y1={topY}
        y2={bottomY}
        stroke={stroke}
        strokeWidth={strokeWidth}
        strokeDasharray={dashArray}
      />
    );
  };


  return (
    <G>
      {renderHorizontalLine(firstTick, strokeSolidColor, strokeSolidWidth)}
      {remainingTicks.map((tick) => renderHorizontalLine(tick, strokeDashColor, strokeDashWidth, dashArray))}
      {includeVertical && xTicks.map((_, index) => renderVerticalLine(index, strokeDashColor, strokeDashWidth, dashArray))}
    </G>
  );
};
