import { useTheme } from "@mui/material";
import moment from "moment";
import React, { useEffect, useMemo, useState } from "react";
import {
  Area,
  AreaChart,
  Legend,
  ReferenceArea,
  ReferenceLine,
  ResponsiveContainer,
  Tooltip,
  TooltipProps,
  XAxis,
  YAxis
} from "recharts";
import MaterialChartTooltip from "./MaterialChartTooltip";
import { blue, orange } from "@mui/material/colors";
import { Payload } from "recharts/types/component/DefaultLegendContent";

export interface SSAreaDataPoint {
  timestamp: number;
  value: number;
}

export interface ColourData {
  colour: string,
  label: string
}

interface Props {
  data: SSAreaDataPoint[];
  tooltipLabel: string
  tooltipUnit?: string
  yAxisLabel: string
  maxRef?: number;
  minRef?: number;
  newXDomain?: number[] | string[];
  multiGraphZoom?: (domain: number[] | string[]) => void;
  colourAboveZero?: ColourData
  colourBelowZero?: ColourData
}

export default function SingleSetAreaChart(props: Props) {
  const { data, maxRef, minRef, newXDomain, multiGraphZoom, yAxisLabel, colourAboveZero, colourBelowZero, tooltipLabel, tooltipUnit } = props;
  const [xDomain, setXDomain] = useState<string[] | number[]>(["dataMin", "dataMax"]);
  const [refLeft, setRefLeft] = useState<number | undefined>();
  const [refRight, setRefRight] = useState<number | undefined>();
  const [legendPayload, setLegendPayload] = useState<Payload[]>([])
  const theme = useTheme();
  const now = moment();

  useEffect(() => {
    if (newXDomain) {
      setXDomain(newXDomain);
    }
  }, [newXDomain]);

  useEffect(() => {
    let legend: Payload[] = []
    if(colourAboveZero){
      legend.push({
        value: colourAboveZero.label,
        color: colourAboveZero.colour,
        id: colourAboveZero.label,
        type: "square"
      })
    }
    if(colourBelowZero){
      legend.push({
        value: colourBelowZero.label,
        color: colourBelowZero.colour,
        id: colourBelowZero.label,
        type: "square"
      })
    }
    setLegendPayload(legend)
  }, [colourAboveZero, colourBelowZero])

  const gradientOffset = useMemo(() => {
  if (!data.length) return 0;

  const values = data.map(p => p.value);
  const max = Math.max(...values);
  const min = Math.min(...values);

  if (max <= 0) return 0;
  if (min >= 0) return 1;

  return max / (max - min);
}, [data]);

  const zoom = () => {
    let newDomain: number[] | string[] = ["dataMin", "dataMax"];
    if (refLeft && refRight && refLeft !== refRight) {
      refLeft < refRight ? (newDomain = [refLeft, refRight]) : (newDomain = [refRight, refLeft]);
      setRefLeft(undefined);
      setRefRight(undefined);
      if (multiGraphZoom) {
        multiGraphZoom(newDomain);
      } else {
        setXDomain(newDomain);
      }
    }
  };

  return (
    <React.Fragment>
      <ResponsiveContainer width={"100%"} height={270}>
        <AreaChart
          data={data}
          onMouseDown={(e: any) => {
            if (e) {
              setRefLeft(e.activeLabel);
            }
          }}
          onMouseMove={(e: any) => {
            if (e) {
              setRefRight(e.activeLabel);
            }
          }}
          onMouseUp={() => {
            setRefLeft(undefined);
            setRefRight(undefined);
            zoom();
          }}>
          <Legend
            verticalAlign="top"
            payload={legendPayload}
          />
          <Tooltip
            animationEasing="ease-out"
            cursor={{ fill: theme.palette.text.primary, opacity: "0.15" }}
            labelFormatter={timestamp => moment(timestamp).format("lll")}
            content={(props: TooltipProps<any, any>) => (
              <MaterialChartTooltip {...props} valueFormatter={value => `${value}` + (tooltipUnit ? tooltipUnit : "")} />
            )}
          />
          <XAxis
            allowDataOverflow
            dataKey="timestamp"
            domain={xDomain}
            name="Time"
            tickFormatter={timestamp => {
              let t = moment(timestamp);
              return now.isSame(t, "day") ? t.format("LT") : t.format("MMM DD");
            }}
            scale="time"
            type="number"
            tick={{ fill: theme.palette.text.primary }}
            stroke={theme.palette.divider}
            interval="preserveStartEnd"
          />
          <YAxis
            type="number"
            domain={["auto", "auto"]}
            label={{
              value: yAxisLabel,
              position: "insideLeft",
              angle: -90,
              fill: theme.palette.text.primary
            }}
          />
          <defs>
            {colourAboveZero && colourBelowZero &&
              <linearGradient id="solidColour" x1="0" y1="0" x2="0" y2="1">
                <stop offset={gradientOffset} stopColor={colourAboveZero.colour} stopOpacity="75%" />
                <stop offset={gradientOffset} stopColor={colourBelowZero.colour} stopOpacity="75%" />
              </linearGradient>
            }
          </defs>
          <Area dataKey={"value"} strokeWidth={3}
            type="monotone"
            name={tooltipLabel}
            stroke={(colourAboveZero && colourBelowZero) && "url(#solidColour)"}
            fill={(colourAboveZero && colourBelowZero) && "url(#solidColour)"}
          />
          <ReferenceLine
            ifOverflow="extendDomain"
            y={maxRef}
            stroke="red"
            strokeDasharray={"5 2"}
          />
          <ReferenceLine
            ifOverflow="extendDomain"
            y={minRef}
            stroke="red"
            strokeDasharray={"5 2"}
          />
          {refLeft && refRight ? (
            <ReferenceArea x1={refLeft} x2={refRight} strokeOpacity={0.3} />
          ) : null}
        </AreaChart>
      </ResponsiveContainer>
    </React.Fragment>
  );
}
