import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useRef, useEffect } from "react";
import * as d3 from "d3";
import { Svg, Tooltip, Wrapper } from "./d3-barchart.styled";
import { isDefined } from "../utils/d3";
import { drawBars, drawLine, drawXAxis, getExtents } from "../utils/d3";
const init = {
    padding: { top: 0, right: 0, bottom: 0, left: 0 },
    barPadding: 10,
    showGrid: { horizontal: false, vertical: false },
    formatterX: (point) => point[0].toString(),
};
const D3BarChart = ({ width, height, charts, padding = init.padding, barPadding = init.barPadding, showGrid = init.showGrid, formatterX = init.formatterX, ...rest }) => {
    const svgRef = useRef(null);
    const tooltipRef = useRef(null);
    const nonce = useRef(0);
    useEffect(() => {
        if (!svgRef.current)
            return;
        if (!charts || charts.length === 0 || !padding)
            return;
        console.info("Barchart:::draw", nonce.current);
        const svg = d3.select(svgRef.current);
        nonce.current = nonce.current + 1;
        svg.selectAll("*").remove();
        const { minY, maxY } = getExtents(charts);
        if (!isDefined(minY) ||
            !isDefined(maxY) ||
            !isDefined(showGrid) ||
            !isDefined(barPadding) ||
            !formatterX)
            return;
        const xDomain = [
            ...new Set(charts.flatMap((el) => el.serie.map(([x, _]) => x))),
        ].sort();
        const xScale = d3
            .scaleBand()
            .domain(xDomain.map((x) => formatterX([x, 0])))
            .range([padding.left, width - padding.right]);
        const yScale = d3
            .scaleLinear()
            .domain([rest.minY ?? minY, rest.maxY ?? maxY])
            .range([height - padding.bottom, padding.top]);
        drawXAxis({
            svg,
            xScale,
            yScale,
            height,
            showGrid,
            padding,
        });
        charts.forEach(({ yOffset }) => yOffset &&
            drawXAxis({
                svg,
                xScale,
                yScale,
                height,
                showGrid,
                yOffset,
                padding,
            }));
        charts.forEach((chartPayload) => chartPayload.type === "bar"
            ? drawBars({
                svg,
                chartPayload,
                height,
                xScale,
                yScale,
                barPadding,
                formatterX,
            })
            : drawLine({
                nonce,
                svg,
                chartPayload,
                xScale,
                yScale,
                strokeWidth: 2,
                xOffset: xScale.bandwidth() / 2,
                formatterX,
            }));
        const tooltip = d3.select(tooltipRef.current);
        const step = xScale.step();
        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);
                }
            });
        });
        const svgBox = svgRef.current.getBoundingClientRect();
        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;
            const i = Math.floor(x / step);
            const xVal = xScale.domain()[i];
            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>&nbsp;&nbsp;<span>${y}</span></p>`, "");
            tooltip
                .html(`<p class="tooltip-label x">${xVal}</p>${info}`)
                .style("opacity", 0.9)
                .style("left", x - 20 + "px")
                .style("top", y - 100 + "px");
        });
    }, [
        svgRef,
        padding,
        width,
        height,
        formatterX,
        showGrid,
        charts,
        barPadding,
        rest.minY,
        rest.maxY,
    ]);
    return (_jsxs(Wrapper, { className: "ui-d3barchart__wrapper", children: [_jsx(Svg, { className: "ui-d3barchart__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][1] !== next[i][1]) {
            result = false;
        }
    }
    return result;
};
export default React.memo(D3BarChart, areEqual);
//# sourceMappingURL=d3-barchart.js.map