import * as d3 from "d3";
import React, { useCallback, useEffect, useRef } from "react";

const GlobeChart = (props) => {
  const ref = useRef();
  const myClass = props.chartClass; // this can be passed in so multiple instances on same page
  let svg = null;
  const chartData = props.data;

  const initiateChart = useCallback(() => {
    //declare svg + get parentElement dimensions
    svg = d3.select(ref.current);
    const parentElement = svg.node().parentElement;
    const chartWidth = parentElement.clientWidth;
    let chartHeight =
      parentElement.clientHeight < 250 ? 250 : parentElement.clientHeight;
    const margins = { left: 0, right: 60, top: 20, bottom: 40 };
    const mapData = props.mapData;
    const chartData = props.data;

    svg.attr("width", chartWidth).attr("height", chartHeight);

    svg
      .select(".backgroundGradient")
      .attr("id", "backgroundGradient")
      .attr("x1", "0%")
      .attr("x2", "0%")
      .attr("y1", "0%")
      .attr("y2", "100%");

    const gradientStops = [
      { offset: "0%", color: "#1C2734" },
      { offset: "80%", color: "#1C2734" },
      { offset: "100%", color: "#EF5DA8" },
    ];

    svg
      .select("#backgroundGradient")
      .selectAll("stop")
      .data(gradientStops)
      .join("stop")
      .attr("offset", (d) => d.offset)
      .attr("stop-color", (d) => d.color);

    const colourRange = ["#249DEE", "#FCA932", "#F5055C"];

    const scaleGradientStops = [
      { offset: "0%", color: colourRange[0] },
      { offset: "50%", color: colourRange[1] },
      { offset: "100%", color: colourRange[2] },
    ];

    svg
      .select(".colourScaleGradient")
      .attr("id", "colourScaleGradient")
      .attr("x1", "0%")
      .attr("x2", "100%")
      .attr("y1", "0%")
      .attr("y2", "0%");

    svg
      .select("#colourScaleGradient")
      .selectAll("stop")
      .data(scaleGradientStops)
      .join("stop")
      .attr("offset", (d) => d.offset)
      .attr("stop-color", (d) => d.color);

    chartData.forEach(function (d) {
      d.meanRelPrice =
        d.relative_prices.length === 0
          ? 0
          : d3.mean(d.relative_prices, (m) => +m.relative_price);
      if (
        mapData.features.find((f) => f.properties.name === d.etf_subgroup) ===
        undefined
      ) {
        console.log(d.etf_subgroup + " is not a valid Country");
      }
    });

    const colourExtent = d3.extent(chartData, (d) => d.meanRelPrice);
    const colourMid =
      colourExtent[0] + Math.abs(colourExtent[1] - colourExtent[0]) / 2;
    const colourScale = d3
      .scaleLinear()
      .domain([colourExtent[0], colourMid, colourExtent[1]])
      .range(colourRange)
      .interpolate(d3.interpolateRgb.gamma(2.2));
    //set project and path
    const projection = d3
      .geoEquirectangular()
      .fitSize(
        [
          chartWidth - margins.left - margins.right,
          chartHeight - margins.top - margins.bottom,
        ],
        mapData
      );

    const path = d3.geoPath().projection(projection);

    const countryGroup = svg
      .select(".mapGroup")
      .selectAll(".countryGroup" + myClass)
      .data(mapData.features, (d) => d.id)
      .join(function (group) {
        const enter = group.append("g").attr("class", "countryGroup" + myClass);
        enter.append("path").attr("class", "countryPath");
        return enter;
      });

    countryGroup
      .select(".countryPath")
      .attr("id", (d) => d.id)
      .attr("d", (d) => path(d))
      .attr("fill", (d) =>
        chartData.find((f) => f.etf_subgroup === d.properties.name) ===
        undefined
          ? "white"
          : colourScale(
              chartData.find((f) => f.etf_subgroup === d.properties.name)
                .meanRelPrice
            )
      )
      //@ts-ignore
      .attr("stroke", "#A0A0A0")
      .attr("stroke-width", 0.25)
      .attr("transform", "translate(" + margins.left + "," + margins.top + ")");

    const mapGroupBounds = svg
      .select(".mapGroup")
      .node()
      .getBoundingClientRect();
    const backgroundRadius =
      mapGroupBounds.width / 2 + margins.left + margins.right;

    svg
      .select(".backgroundCircle")
      .attr("r", backgroundRadius)
      .attr("fill", "url(#backgroundGradient)")
      .attr("transform", "translate(" + chartWidth / 2 + ",0)");

    chartHeight = backgroundRadius;

    svg.attr("height", chartHeight);

    svg
      .select(".gradientRect")
      .attr("width", backgroundRadius / 2)
      .attr("height", 20)
      .attr("fill", "url(#colourScaleGradient)")
      .attr("transform", "translate(0," + (chartHeight - 20) + ")");

    svg
      .select(".gradientLabel")
      .attr("font-size", 12)
      .attr("fill", "#686868")
      .text("Country Relative Strength vs. SPY")
      .attr("transform", "translate(0," + (chartHeight - 30) + ")");
  });

  useEffect(() => {
    //copied this from another project
    initiateChart();
  }, [initiateChart, props.data]);

  return (
    <svg ref={ref}>
      <defs>
        <linearGradient className={"backgroundGradient"}></linearGradient>
        <linearGradient className={"colourScaleGradient"}></linearGradient>
      </defs>
      <circle className={"backgroundCircle"}></circle>
      <g className={"mapGroup"}></g>
      <text className={"gradientLabel"}></text>
      <rect className={"gradientRect"}></rect>
    </svg>
  );
};

GlobeChart.propTypes = {};

export default GlobeChart;
