import { AxisBottom, AxisLeft } from "@visx/axis";
import { bottomTickLabelProps } from "@visx/axis/lib/axis/AxisBottom";
import * as allCurves from "@visx/curve";
import { Group } from "@visx/group";
import { scaleBand, scaleLinear } from "@visx/scale";
import { LinePath } from "@visx/shape";
import { extent, max } from "d3-array";
import { Color } from "utils/Color";

type CurveType = keyof typeof allCurves;

const curveTypes = Object.keys(allCurves);
const lineCount = 2;
// const series = new Array(lineCount).fill(null).map((_, i) =>
//   // vary each series value deterministically
//   generateDateValue(25, /* seed= */ i / 72).sort(
//     (a: DateValue, b: DateValue) => a.date.getTime() - b.date.getTime()
//   )
// );

interface LineData {
  label: string;
  yValues: number[];
}

interface PointData {
  x: string;
  y: number;
}

interface LineGraphData {
  xValues: string[];
  lines: LineData[];
}

interface LineGraphProps {
  data: LineGraphData;
  /** Width of the entire graph, in pixels. */
  width: number;
  /** Height of the entire graph, in pixels. */
  height: number;
  /** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
  margin: {
    top: number;
    bottom: number;
    left: number;
    right: number;
  };
  className?: string;
  /** Font size of the category tick labels, in pixels. Default is 16px. */
  xTickLabelSize?: number;
  /** Font size of the value tick labels, in pixels. Default is 16px. */
  yTickLabelSize?: number;
  /** Font size of the value that appears when hovering over a bar, in pixels. */
  hoverLabelSize?: number;
  /** Label text for the category axis. */
  xAxisLabel?: string;
  /** Font size of the label for the cateogry axis, in pixels. */
  xAxisLabelSize?: number;
  /** Controls the distance between the category axis label and the category axis. */
  xAxisLabelOffset?: number;
  /** Label text for the value axis. */
  yAxisLabel?: string;
  /** Font size of the label for the value axis, in pixels. */
  yAxisLabelSize?: number;
  /** Controls the distance between the value axis label and the value axis. */
  yAxisLabelOffset?: number;
}

const DEFAULT_LABEL_SIZE = 16;

export function LineGraph(props: LineGraphProps) {
  const {
    width,
    height,
    margin,
    data,
    className,
    xTickLabelSize = DEFAULT_LABEL_SIZE,
    yTickLabelSize = DEFAULT_LABEL_SIZE,
    hoverLabelSize,
    xAxisLabel,
    xAxisLabelSize = DEFAULT_LABEL_SIZE,
    xAxisLabelOffset = 0,
    yAxisLabel,
    yAxisLabelSize = DEFAULT_LABEL_SIZE,
    yAxisLabelOffset = 0,
  } = props;

  const curveType = "curveLinear";
  const svgHeight = height - 40;
  //const allData = data.reduce((rec, d) => rec.concat(d), []);
  //console.log(allData);

  // update scale output ranges

  const yMax = height - margin.top - margin.bottom;
  const xMax = width - margin.left - margin.right;

  const actualData = data.lines.map((line) => {
    return line.yValues.map((val, idx) => {
      return { x: data.xValues[idx], y: val };
    });
  });

  // data accessors
  const getX = (d: PointData) => d.x;
  const getY = (d: PointData) => d.y;

  // scales
  const xScale = scaleBand({
    range: [0, xMax],
    domain: data.xValues,
  });
  const yScale = scaleLinear<number>({
    range: [0, yMax],
    nice: true,
    domain: [0, 100],
  });

  return (
    <svg width={width} height={svgHeight}>
      <Group top={margin.top} left={margin.left}>
        {actualData.map((lineData, i) => {
          console.log(lineData);
          const even = i % 2 === 0;
          return (
            <Group key={`line-${i}`}>
              <LinePath
                curve={allCurves[curveType]}
                data={lineData}
                x={(d) => xScale(getX(d)) ?? 0}
                y={(d) => yScale(getY(d)) ?? 0}
                stroke={even ? Color.primaryAccent : Color.secondaryAccent}
                strokeWidth={2}
                strokeOpacity={2}
              />
            </Group>
          );
        })}
      </Group>
      <AxisBottom
        scale={xScale}
        top={margin.top + yMax}
        left={margin.left}
        hideAxisLine
        hideTicks
        tickLabelProps={() => {
          return {
            ...bottomTickLabelProps(),
            //className: styles.tickLabel,
            dy: "-0.25rem",
            fontSize: `${xTickLabelSize / 16}rem`,
            //width: categoryScale.bandwidth(),
            verticalAnchor: "start",
          };
        }}
        label={xScale}
        // labelClassName={styles.axisLabel}
        labelOffset={xAxisLabelOffset}
        labelProps={{
          fontSize: `${xAxisLabelSize / 16}rem`,
        }}
      />
    </svg>
  );
}
