import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as d3 from "d3";
import React, { useRef, useEffect } from "react";
import { Svg, Tooltip, Wrapper } from "./d3-linechart.styled";
import { getClosest } from "../utils/d3";
import { drawLine, drawXAxis, drawGradient, getExtents, isDefined, } from "../utils/d3";
const init = {
    padding: { top: 0, right: 0, bottom: 0, left: 0 },
    showGrid: { horizontal: false, vertical: false },
    formatterX: (d) => d[0].toString(),
    pointToHuman: ([x, y]) => [x.toString(), y.toString()],
    lineWidth: 2,
};
const D3LineChart = ({ height, width, charts, padding = init.padding, showGrid = init.showGrid, formatterX = init.formatterX, pointToHuman = init.pointToHuman, lineWidth = init.lineWidth, showGradient = true, }) => {
    const svgRef = useRef(null);
    const tooltipRef = useRef(null);
    const nonce = useRef(0);
    useEffect(() => {
        if (!svgRef.current ||
            !padding ||
            !showGrid ||
            !lineWidth ||
            !formatterX ||
            !pointToHuman)
            return;
        if (!charts || charts.length === 0)
            return;
        const svg = d3.select(svgRef.current);
        svg.selectAll("*").remove();
        const { minY, maxY, minX, maxX } = getExtents(charts);
        if (!isDefined(minY) ||
            !isDefined(maxY) ||
            !isDefined(minX) ||
            !isDefined(maxX))
            return;
        nonce.current = nonce.current + 1;
        console.info("Linechart:::draw", nonce.current);
        const xScale = d3
            .scaleLinear()
            .domain([minX, maxX])
            .range([padding.left, width - padding.right]);
        var yScale = d3
            .scaleLinear()
            .domain([minY, maxY])
            .range([height - padding.top, padding.bottom]);
        drawXAxis({
            svg,
            xScale,
            yScale,
            height,
            showGrid: showGrid,
        });
        showGradient &&
            charts.forEach((chartPayload) => {
                drawGradient({
                    svg,
                    chartPayload,
                    xScale,
                    yScale,
                });
            });
        charts.forEach((chartPayload) => drawLine({
            nonce,
            svg,
            chartPayload,
            xScale,
            yScale,
            strokeWidth: lineWidth,
            formatterX,
        }));
        const tooltip = d3.select(tooltipRef.current);
        const svgBox = svgRef.current.getBoundingClientRect();
        if (!tooltip || !svgBox)
            return;
        const tooltipsMem = {};
        charts.forEach((chart) => {
            const { id, title, color } = chart;
            chart.serie.forEach((point) => {
                const xFormatted = formatterX(point);
                const newEl = { id, title, color, y: point[1] };
                if (!tooltipsMem[xFormatted]) {
                    tooltipsMem[xFormatted] = [newEl];
                }
                else {
                    tooltipsMem[xFormatted].push(newEl);
                }
            });
        });
        svg
            .on("mouseleave", () => tooltip.transition().duration(500).style("opacity", 0))
            .on("mousemove", (event) => {
            const pointer = d3.pointer(event, svg);
            const x = pointer[0] - svgBox.left;
            const y = pointer[1] - svgBox.top;
            // fake serie
            const serie = Object.keys(tooltipsMem).map((el) => [
                Number(el),
                0,
            ]);
            const [xVal] = getClosest({ x, xScale, serie });
            if (!xVal || !tooltipsMem[xVal])
                return;
            const info = tooltipsMem[xVal].reduce((acc, { id, title, color, y }) => `${acc}<p class="tooltip-label ${id}" style="color:${color}"><span>${title}</span> <span>${pointToHuman([0, y])[1]}</span></p>`, "");
            tooltip
                .html(`<p class="tooltip-label x">${pointToHuman([xVal, 0])[0]}</p>${info}`)
                .style("opacity", 0.9)
                .style("left", x - 20 + "px")
                .style("top", y - 100 + "px");
        });
    }, [
        svgRef,
        formatterX,
        charts,
        showGrid,
        width,
        height,
        padding,
        showGradient,
        lineWidth,
        pointToHuman,
    ]);
    return (_jsxs(Wrapper, { className: "ui-d3linechart__wrapper", children: [_jsx(Svg, { className: "ui-d3linechart__svg", style: { height, width }, ref: svgRef }), _jsx(Tooltip, { ref: tooltipRef })] }));
};
const areEqual = (prevProps, nextProps) => {
    if (nextProps.width !== prevProps.width) {
        return false;
    }
    let result = true;
    const prev = prevProps.charts.flatMap((el) => el.serie);
    const next = nextProps.charts.flatMap((el) => el.serie);
    if (prev.length !== next.length)
        return false;
    const size = prev.length;
    for (let i = 0; i < size; i++) {
        if (prev[i].length !== next[i].length) {
            result = false;
        }
        if (prev[i][0] !== next[i][0]) {
            result = false;
        }
        if (size > 0 && prev[i][size - 1] !== next[i][size - 1]) {
            result = false;
        }
    }
    return result;
};
export default React.memo(D3LineChart, areEqual);
//# sourceMappingURL=d3-linechart.js.map