import { extent, max, min, bisector } from "d3";
import { safeToFixed } from "../../utils/format";
import { ENABLE_DEBUG } from "./constants";
export const defaultMapper = (el) => el;
export const defaultFormatter = (d) => d.toString();
export const pickY = ([_, y]) => y;
export const pickX = ([x, _]) => x;
export const getExtents = (data, stacked) => {
    const [minX, maxX] = extent(data, (d) => d.x);
    const minY = min(stacked, (d) => min(d, (e) => e[1]));
    const maxY = max(stacked, (d) => max(d, (e) => e[1]));
    return { minX, maxX, minY, maxY };
};
export const isVoid = (el) => el === undefined;
export const isNotVoid = (el) => el !== undefined;
export const getXAxisShift = ({ height, margin, extents, positiveExtents, }) => {
    const { minY, maxY } = extents;
    if (minY === undefined ||
        maxY === undefined ||
        positiveExtents.maxY === undefined ||
        positiveExtents.minY === undefined)
        return undefined;
    const kPositive = (positiveExtents.maxY - positiveExtents.minY) / (maxY - minY);
    const xAxisShift = margin.top + kPositive * (height - margin.top - margin.bottom);
    return xAxisShift;
};
export const drawFocus = ({ svg, color, }) => {
    // graph point highlight styling
    const focus = svg.append("g");
    focus
        .append("circle")
        .style("fill", color)
        .style("opacity", 0.3)
        .attr("r", 8);
    focus.append("circle").style("fill", "white").attr("r", 6);
    focus.append("circle").style("fill", color).attr("r", 4);
    focus.style("visibility", "hidden");
    return focus;
};
export const showFocus = ({ focus, xScale, yScale, closest, }) => {
    const x = xScale(closest[0]);
    const y = yScale(closest[1]);
    focus
        .style("visibility", "visible")
        .selectAll("circle")
        .attr("transform", `translate(${x}, ${y})`);
};
export const hideFocus = (focus) => {
    focus.style("visibility", "hidden");
};
export const bisectLeft = bisector((d) => d[0]).left;
const getClosestPointId = ({ x, xScale, serie, }) => {
    const x0 = xScale.invert(x);
    const i = bisectLeft(serie, x0, 1, serie.length - 1);
    const d0 = serie[i - 1];
    const d1 = serie[i];
    const result = typeof d1 !== "undefined" && x0 - d0[0] > d1[0] - x0 ? i : i - 1;
    return result;
};
export const getClosest = ({ x, xScale, serie, }) => {
    const pointId = getClosestPointId({
        x,
        xScale,
        serie,
    });
    return serie[pointId];
};
export const toHex = (s) => s
    .split("")
    .map((el) => el.charCodeAt(0).toString(16))
    .join("");
export const getTooltipClass = (graph) => `id${toHex(graph)}`;
const getTooltipLine = ({ markerColor, title, value, }) => `<div class="tooltip-text">
<div class="tooltip-text__marker" style="border: 5px solid ${markerColor}"></div>
<div class="tooltip-text__title">${title}: </div>
<div class="tooltip-text__value">${value}</div>
</div>`;
export const getTooltipHtml = ({ serie, closestX, }) => {
    const { data, keysPositive, keysNegative, colorsNegative, colorsPositive, } = serie;
    const colors = new Map();
    const record = data.find(({ x }) => x === closestX);
    if (isVoid(record))
        return;
    for (let i = 0; i < keysPositive.length; i++) {
        colors.set(keysPositive[i], colorsPositive[i]);
    }
    for (let i = 0; i < keysNegative.length; i++) {
        colors.set(keysNegative[i], colorsNegative[i]);
    }
    const usedKeys = [...keysPositive, ...keysNegative];
    const filteredValues = Object.entries(record.y).filter(([k, _]) => usedKeys.includes(k));
    const total = filteredValues.reduce((acc, [_, v]) => acc + v, 0);
    const html = filteredValues.map(([k, v]) => {
        return getTooltipLine({
            markerColor: colors.get(k),
            title: k,
            value: safeToFixed(Math.abs(v), 2),
        });
    });
    const totalHtml = getTooltipLine({
        markerColor: "#E8662D",
        title: "Total: ",
        value: safeToFixed(total, 2),
    });
    const at = new Date(record.x);
    const recordDate = getTooltipLine({
        markerColor: "transparent",
        title: at.toLocaleDateString(),
        value: at.toLocaleTimeString(),
    });
    return [recordDate, totalHtml, ...html].join("");
};
export const showTooltip = ({ x, tooltip, closest, xScale, yScale, width, serie, }) => {
    const dx = 10;
    const dy = 5;
    const html = getTooltipHtml({ serie, closestX: closest[0] });
    const isLeft = xScale(closest[0]) < width / 2;
    tooltip
        .style("opacity", 1)
        .style("top", yScale(closest[1]) - dy + "px")
        .html(`<div class="tooltip-group">${html}</div>`);
    if (isLeft) {
        tooltip.style("right", "unset");
        tooltip.style("left", xScale(closest[0]) + dx + "px");
    }
    else {
        tooltip.style("left", "unset");
        tooltip.style("right", width - xScale(closest[0]) + dx + "px");
    }
};
export const hideTooltip = (tooltip) => {
    tooltip.style("opacity", 0);
};
export const debug = (label, ...args) => ENABLE_DEBUG && console.info(`${label}:::`, ...args);
//# sourceMappingURL=utils.js.map