import getStroke from 'perfect-freehand';
const BRUSH_DEFAULTS = {
    // Tapered, pressure-responsive — feels like an ink pen.
    pen: { thinning: 0.6, smoothing: 0.5, streamline: 0.5, taperStart: true, taperEnd: true },
    // Flat, even width — a chisel marker.
    marker: { thinning: 0.1, smoothing: 0.55, streamline: 0.5, taperStart: false, taperEnd: false },
    // Even width like marker; the translucency comes from element opacity.
    highlighter: { thinning: 0, smoothing: 0.6, streamline: 0.5, taperStart: false, taperEnd: false }
};
export function resolveStrokeOptions(el) {
    const d = BRUSH_DEFAULTS[el.brush] ?? BRUSH_DEFAULTS.pen;
    return {
        size: el.strokeWidth,
        thinning: el.thinning ?? d.thinning ?? 0.5,
        smoothing: el.smoothing ?? d.smoothing ?? 0.5,
        streamline: el.streamline ?? d.streamline ?? 0.5,
        taperStart: el.taperStart ?? d.taperStart ?? false,
        taperEnd: el.taperEnd ?? d.taperEnd ?? false
    };
}
/** Turn a perfect-freehand outline polygon into an SVG path `d` string. */
function outlineToPath(points) {
    if (points.length === 0)
        return '';
    const d = points.reduce((acc, [x0, y0], i, arr) => {
        const [x1, y1] = arr[(i + 1) % arr.length];
        acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
        return acc;
    }, ['M', points[0][0], points[0][1], 'Q']);
    d.push('Z');
    return d.join(' ');
}
/** Compute the axis-aligned bounding box of raw input points. */
export function pointsBounds(points) {
    if (points.length === 0)
        return { minX: 0, minY: 0, width: 0, height: 0 };
    let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
    for (const [x, y] of points) {
        if (x < minX)
            minX = x;
        if (y < minY)
            minY = y;
        if (x > maxX)
            maxX = x;
        if (y > maxY)
            maxY = y;
    }
    return { minX, minY, width: maxX - minX, height: maxY - minY };
}
/**
 * Build the renderable path + viewBox for a draw element. Points are assumed
 * to already be in a 0,0-origin local space; the viewBox spans their bounds
 * (plus stroke padding) so the element box scales the stroke on resize.
 */
export function drawElementToPath(el) {
    const opts = resolveStrokeOptions(el);
    const stroke = getStroke(el.points, {
        size: opts.size,
        thinning: opts.thinning,
        smoothing: opts.smoothing,
        streamline: opts.streamline,
        start: { taper: opts.taperStart ? opts.size * 4 : 0, cap: !opts.taperStart },
        end: { taper: opts.taperEnd ? opts.size * 4 : 0, cap: !opts.taperEnd }
    });
    const d = outlineToPath(stroke);
    const b = pointsBounds(el.points);
    const pad = opts.size;
    const vb = `${b.minX - pad} ${b.minY - pad} ${b.width + pad * 2} ${b.height + pad * 2}`;
    return { d, viewBox: vb };
}
