import { jsxs, jsx } from 'react/jsx-runtime';
import React from 'react';

// ── Defaults ────────────────────────────────────────────────────
const DEFAULT_METRICS = {
    unitsPerEm: 1000,
    ascent: 800,
    descent: -200,
    lineGap: 0,
    xHeight: 500,
    capHeight: 700,
};
const BASIC_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,:;!?-'\"()[]{}@#$%&*+=/\\<>~`^|_";
function createDefaultGlyphs() {
    return Array.from(BASIC_CHARS).map((char) => ({
        unicode: char.codePointAt(0),
        char,
        name: char === " " ? "space" : `uni${char.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")}`,
        path: "",
        advanceWidth: 500,
        leftBearing: 50,
    }));
}
// ── SVG Font Export ─────────────────────────────────────────────
function exportToSvgFont(data) {
    const glyphElements = data.glyphs
        .filter((g) => g.path)
        .map((g) => `    <glyph unicode="&#x${g.unicode.toString(16)};" glyph-name="${g.name}" d="${g.path}" horiz-adv-x="${g.advanceWidth}" />`)
        .join("\n");
    return `<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <font id="${data.family}" horiz-adv-x="${data.metrics.unitsPerEm}">
      <font-face
        font-family="${data.family}"
        font-weight="400"
        font-style="normal"
        units-per-em="${data.metrics.unitsPerEm}"
        ascent="${data.metrics.ascent}"
        descent="${data.metrics.descent}"
        x-height="${data.metrics.xHeight}"
        cap-height="${data.metrics.capHeight}"
      />
      <missing-glyph horiz-adv-x="${data.metrics.unitsPerEm * 0.5}" />
${glyphElements}
    </font>
  </defs>
</svg>`;
}
// ── Hook ────────────────────────────────────────────────────────
function useFontEditor(initialName) {
    const [fontName, setFontName] = React.useState(initialName);
    const [metrics, setMetrics] = React.useState(DEFAULT_METRICS);
    const [glyphs, setGlyphs] = React.useState(createDefaultGlyphs);
    const [selectedGlyph, setSelectedGlyph] = React.useState(null);
    const [previewText, setPreviewText] = React.useState("The quick brown fox jumps over the lazy dog");
    const [historyIdx, setHistoryIdx] = React.useState(0);
    const historyRef = React.useRef([]);
    React.useEffect(() => {
        historyRef.current = [JSON.parse(JSON.stringify(glyphs))];
    }, []); // eslint-disable-line
    const pushHistory = React.useCallback((newGlyphs) => {
        historyRef.current = historyRef.current.slice(0, historyIdx + 1);
        historyRef.current.push(JSON.parse(JSON.stringify(newGlyphs)));
        if (historyRef.current.length > 40)
            historyRef.current.shift();
        setHistoryIdx(historyRef.current.length - 1);
    }, [historyIdx]);
    const updateGlyph = React.useCallback((unicode, updates) => {
        const newGlyphs = glyphs.map((g) => g.unicode === unicode ? { ...g, ...updates } : g);
        setGlyphs(newGlyphs);
        pushHistory(newGlyphs);
    }, [glyphs, pushHistory]);
    const addGlyph = React.useCallback((char) => {
        const unicode = char.codePointAt(0);
        if (glyphs.some((g) => g.unicode === unicode))
            return;
        const newGlyphs = [...glyphs, {
                unicode,
                char,
                name: `uni${unicode.toString(16).toUpperCase().padStart(4, "0")}`,
                path: "",
                advanceWidth: 500,
                leftBearing: 50,
            }];
        setGlyphs(newGlyphs);
        pushHistory(newGlyphs);
    }, [glyphs, pushHistory]);
    const toFontData = React.useCallback(() => ({
        name: fontName,
        family: fontName.replace(/\s+/g, ""),
        metrics,
        glyphs,
    }), [fontName, metrics, glyphs]);
    return {
        fontName, setFontName,
        metrics, setMetrics,
        glyphs, selectedGlyph, setSelectedGlyph,
        updateGlyph, addGlyph,
        previewText, setPreviewText,
        toFontData,
    };
}
// ── Component ───────────────────────────────────────────────────
/** Font glyph editor with metrics, visual path editing, and preview. */
const NiceFontEditor = ({ fontName = "MyFont", onSave, className = "", }) => {
    var _a;
    const editor = useFontEditor(fontName);
    const [drawMode, setDrawMode] = React.useState("select");
    const [pathPoints, setPathPoints] = React.useState([]);
    const [tab, setTab] = React.useState("glyph");
    const [kerningPairs, setKerningPairs] = React.useState([]);
    const [newKernLeft, setNewKernLeft] = React.useState("A");
    const [newKernRight, setNewKernRight] = React.useState("V");
    const [showGrid, setShowGrid] = React.useState(true);
    const handleSave = () => onSave === null || onSave === void 0 ? void 0 : onSave(editor.toFontData());
    const handleExportSvg = () => {
        const data = editor.toFontData();
        const svg = exportToSvgFont(data);
        const blob = new Blob([svg], { type: "image/svg+xml" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `${data.family}.svg`;
        a.click();
        URL.revokeObjectURL(url);
    };
    const selectedG = editor.selectedGlyph !== null
        ? (_a = editor.glyphs.find((g) => g.unicode === editor.selectedGlyph)) !== null && _a !== void 0 ? _a : null
        : null;
    const em = editor.metrics.unitsPerEm;
    // Click on glyph SVG to add path control points
    const handleGlyphCanvasClick = (e) => {
        if (drawMode !== "pen" || !selectedG)
            return;
        const svg = e.currentTarget;
        const rect = svg.getBoundingClientRect();
        const x = Math.round(((e.clientX - rect.left) / rect.width) * em);
        const y = Math.round(((e.clientY - rect.top) / rect.height) * em);
        const newPoints = [...pathPoints, { x, y }];
        setPathPoints(newPoints);
        // Build SVG path from points
        if (newPoints.length >= 2) {
            let d = `M ${newPoints[0].x} ${newPoints[0].y}`;
            for (let i = 1; i < newPoints.length; i++)
                d += ` L ${newPoints[i].x} ${newPoints[i].y}`;
            d += " Z";
            editor.updateGlyph(selectedG.unicode, { path: d });
        }
    };
    const clearPath = () => {
        setPathPoints([]);
        if (selectedG)
            editor.updateGlyph(selectedG.unicode, { path: "" });
    };
    const btnStyle = (active) => ({
        padding: "4px 8px", borderRadius: 3, border: "none", cursor: "pointer",
        background: active ? "#339af0" : "#2c2e33", color: active ? "#fff" : "#c1c2c5", fontSize: 11,
    });
    const fieldStyle = {
        width: "100%", background: "#2c2e33", color: "#c1c2c5",
        border: "1px solid #373a40", borderRadius: 3, padding: "2px 4px", fontSize: 10,
    };
    const tabBtnStyle = (active) => ({
        padding: "4px 12px", border: "none", borderBottom: active ? "2px solid #339af0" : "2px solid transparent",
        background: "transparent", color: active ? "#fff" : "#868e96", cursor: "pointer", fontSize: 11,
    });
    return (jsxs("div", { className: `nice-font-editor ${className}`, style: { display: "flex", flexDirection: "column", gap: 8, background: "#1a1b1e", color: "#c1c2c5", padding: 12, borderRadius: 8 }, children: [jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 12 }, children: [jsx("strong", { style: { fontSize: 14 }, children: "Font Editor" }), jsx("input", { value: editor.fontName, onChange: e => editor.setFontName(e.target.value), placeholder: "Font name", style: { flex: 1, maxWidth: 200, ...fieldStyle, fontSize: 12 } }), jsx("button", { onClick: handleSave, style: { padding: "4px 12px", background: "#2f9e44", color: "#fff", border: "none", borderRadius: 3, cursor: "pointer", fontSize: 11 }, children: "Save" }), jsx("button", { onClick: handleExportSvg, style: { padding: "4px 12px", background: "#228be6", color: "#fff", border: "none", borderRadius: 3, cursor: "pointer", fontSize: 11 }, children: "Export SVG Font" })] }), jsxs("div", { style: { display: "flex", gap: 4, borderBottom: "1px solid #373a40" }, children: [jsx("button", { onClick: () => setTab("glyph"), style: tabBtnStyle(tab === "glyph"), children: "Glyphs" }), jsx("button", { onClick: () => setTab("metrics"), style: tabBtnStyle(tab === "metrics"), children: "Metrics" }), jsx("button", { onClick: () => setTab("kerning"), style: tabBtnStyle(tab === "kerning"), children: "Kerning" })] }), tab === "glyph" && (jsxs("div", { style: { display: "flex", gap: 8 }, children: [jsxs("div", { style: { flex: 1 }, children: [jsxs("div", { style: { fontSize: 11, marginBottom: 4, color: "#868e96" }, children: [editor.glyphs.length, " glyphs"] }), jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, 36px)", gap: 2, maxHeight: 300, overflowY: "auto" }, children: editor.glyphs.map((g) => (jsx("div", { onClick: () => { editor.setSelectedGlyph(g.unicode); setPathPoints([]); }, title: `U+${g.unicode.toString(16).toUpperCase().padStart(4, "0")} - ${g.name}`, style: {
                                        width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center",
                                        borderRadius: 3, cursor: "pointer", fontSize: 16,
                                        background: editor.selectedGlyph === g.unicode ? "#339af0" : (g.path ? "#2c2e33" : "#25262b"),
                                        color: editor.selectedGlyph === g.unicode ? "#fff" : (g.path ? "#c1c2c5" : "#5c5f66"),
                                        border: g.path ? "1px solid #373a40" : "1px solid transparent",
                                    }, children: g.char }, g.unicode))) })] }), jsx("div", { style: { width: 320, fontSize: 11 }, children: selectedG ? (jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxs("strong", { children: ["\"", selectedG.char, "\" (U+", selectedG.unicode.toString(16).toUpperCase().padStart(4, "0"), ")"] }), jsxs("div", { style: { display: "flex", gap: 2 }, children: [jsx("button", { onClick: () => setDrawMode("select"), style: btnStyle(drawMode === "select"), children: "Select" }), jsx("button", { onClick: () => setDrawMode("pen"), style: btnStyle(drawMode === "pen"), children: "Pen" }), jsx("button", { onClick: clearPath, style: btnStyle(false), children: "Clear" }), jsx("button", { onClick: () => setShowGrid(g => !g), style: btnStyle(showGrid), children: "Grid" })] })] }), jsxs("svg", { width: 280, height: 280, viewBox: `0 0 ${em} ${em}`, style: { background: "#141517", borderRadius: 4, cursor: drawMode === "pen" ? "crosshair" : "default" }, onClick: handleGlyphCanvasClick, children: [showGrid && Array.from({ length: 11 }, (_, i) => {
                                            const pos = (i / 10) * em;
                                            return (jsxs(React.Fragment, { children: [jsx("line", { x1: pos, y1: 0, x2: pos, y2: em, stroke: "rgba(255,255,255,0.05)", strokeWidth: em * 0.002 }), jsx("line", { x1: 0, y1: pos, x2: em, y2: pos, stroke: "rgba(255,255,255,0.05)", strokeWidth: em * 0.002 })] }, i));
                                        }), jsx("line", { x1: 0, y1: em - editor.metrics.ascent, x2: em, y2: em - editor.metrics.ascent, stroke: "rgba(51,154,240,0.3)", strokeWidth: em * 0.003, strokeDasharray: `${em * 0.01}` }), jsx("line", { x1: 0, y1: em, x2: em, y2: em, stroke: "rgba(47,158,68,0.3)", strokeWidth: em * 0.003 }), jsx("line", { x1: 0, y1: em - editor.metrics.xHeight, x2: em, y2: em - editor.metrics.xHeight, stroke: "rgba(249,226,175,0.3)", strokeWidth: em * 0.003, strokeDasharray: `${em * 0.01}` }), jsx("line", { x1: 0, y1: em - editor.metrics.capHeight, x2: em, y2: em - editor.metrics.capHeight, stroke: "rgba(243,139,168,0.3)", strokeWidth: em * 0.003, strokeDasharray: `${em * 0.01}` }), jsx("line", { x1: selectedG.leftBearing, y1: 0, x2: selectedG.leftBearing, y2: em, stroke: "rgba(166,227,161,0.2)", strokeWidth: em * 0.002 }), jsx("line", { x1: selectedG.advanceWidth, y1: 0, x2: selectedG.advanceWidth, y2: em, stroke: "rgba(243,139,168,0.2)", strokeWidth: em * 0.002 }), selectedG.path && jsx("path", { d: selectedG.path, fill: "rgba(205,214,244,0.8)", stroke: "#89b4fa", strokeWidth: em * 0.005 }), pathPoints.map((p, i) => (jsx("circle", { cx: p.x, cy: p.y, r: em * 0.015, fill: i === 0 ? "#2f9e44" : "#339af0", stroke: "#fff", strokeWidth: em * 0.003 }, i))), jsx("text", { x: em * 0.02, y: em - editor.metrics.ascent - em * 0.01, fill: "rgba(51,154,240,0.5)", fontSize: em * 0.03, children: "ascent" }), jsx("text", { x: em * 0.02, y: em - editor.metrics.xHeight - em * 0.01, fill: "rgba(249,226,175,0.5)", fontSize: em * 0.03, children: "x-height" }), jsx("text", { x: em * 0.02, y: em - editor.metrics.capHeight - em * 0.01, fill: "rgba(243,139,168,0.5)", fontSize: em * 0.03, children: "cap" })] }), jsxs("div", { children: [jsx("label", { children: "SVG Path" }), jsx("textarea", { value: selectedG.path, onChange: e => editor.updateGlyph(selectedG.unicode, { path: e.target.value }), rows: 3, style: { ...fieldStyle, fontFamily: "monospace", resize: "vertical" } })] }), jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4 }, children: [jsx("label", { children: "Advance Width" }), jsx("input", { type: "number", value: selectedG.advanceWidth, onChange: e => editor.updateGlyph(selectedG.unicode, { advanceWidth: Number(e.target.value) }), style: fieldStyle }), jsx("label", { children: "Left Bearing" }), jsx("input", { type: "number", value: selectedG.leftBearing, onChange: e => editor.updateGlyph(selectedG.unicode, { leftBearing: Number(e.target.value) }), style: fieldStyle })] })] })) : (jsx("div", { style: { color: "#868e96", padding: 20, textAlign: "center" }, children: "Select a glyph to edit" })) })] })), tab === "metrics" && (jsxs("div", { style: { maxWidth: 400 }, children: [jsx("strong", { style: { fontSize: 12, display: "block", marginBottom: 8 }, children: "Font Metrics" }), [
                        ["unitsPerEm", "Units per Em"],
                        ["ascent", "Ascent"],
                        ["descent", "Descent"],
                        ["lineGap", "Line Gap"],
                        ["xHeight", "x-Height"],
                        ["capHeight", "Cap Height"],
                    ].map(([key, label]) => (jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }, children: [jsx("span", { style: { minWidth: 100, fontSize: 11 }, children: label }), jsx("input", { type: "number", value: editor.metrics[key], onChange: e => editor.setMetrics({ ...editor.metrics, [key]: Number(e.target.value) }), style: fieldStyle })] }, key))), jsxs("svg", { width: 300, height: 200, viewBox: `0 0 ${em} ${em}`, style: { background: "#141517", borderRadius: 4, marginTop: 12 }, children: [jsx("rect", { x: 0, y: em - editor.metrics.ascent, width: em, height: editor.metrics.ascent - editor.metrics.descent, fill: "rgba(51,154,240,0.05)", stroke: "rgba(51,154,240,0.2)", strokeWidth: em * 0.003 }), jsx("line", { x1: 0, y1: em - editor.metrics.ascent, x2: em, y2: em - editor.metrics.ascent, stroke: "#339af0", strokeWidth: em * 0.004 }), jsx("line", { x1: 0, y1: em, x2: em, y2: em, stroke: "#2f9e44", strokeWidth: em * 0.004 }), jsx("line", { x1: 0, y1: em + Math.abs(editor.metrics.descent), x2: em, y2: em + Math.abs(editor.metrics.descent), stroke: "#e03131", strokeWidth: em * 0.004 }), jsx("line", { x1: 0, y1: em - editor.metrics.xHeight, x2: em, y2: em - editor.metrics.xHeight, stroke: "#f9e2af", strokeWidth: em * 0.003, strokeDasharray: `${em * 0.015}` }), jsx("line", { x1: 0, y1: em - editor.metrics.capHeight, x2: em, y2: em - editor.metrics.capHeight, stroke: "#f38ba8", strokeWidth: em * 0.003, strokeDasharray: `${em * 0.015}` }), jsxs("text", { x: em * 0.02, y: em - editor.metrics.ascent + em * 0.05, fill: "#339af0", fontSize: em * 0.04, children: ["Ascent (", editor.metrics.ascent, ")"] }), jsx("text", { x: em * 0.02, y: em + em * 0.05, fill: "#2f9e44", fontSize: em * 0.04, children: "Baseline" }), jsxs("text", { x: em * 0.02, y: em - editor.metrics.xHeight + em * 0.05, fill: "#f9e2af", fontSize: em * 0.04, children: ["x-Height (", editor.metrics.xHeight, ")"] }), jsxs("text", { x: em * 0.02, y: em - editor.metrics.capHeight + em * 0.05, fill: "#f38ba8", fontSize: em * 0.04, children: ["Cap (", editor.metrics.capHeight, ")"] })] })] })), tab === "kerning" && (jsxs("div", { style: { maxWidth: 500 }, children: [jsx("strong", { style: { fontSize: 12, display: "block", marginBottom: 8 }, children: "Kerning Pairs" }), jsxs("div", { style: { display: "flex", gap: 4, marginBottom: 8, alignItems: "center", fontSize: 11 }, children: [jsx("input", { value: newKernLeft, onChange: e => setNewKernLeft(e.target.value), maxLength: 1, style: { ...fieldStyle, width: 30, textAlign: "center" } }), jsx("input", { value: newKernRight, onChange: e => setNewKernRight(e.target.value), maxLength: 1, style: { ...fieldStyle, width: 30, textAlign: "center" } }), jsx("button", { onClick: () => {
                                    if (newKernLeft && newKernRight) {
                                        setKerningPairs(prev => [...prev, { left: newKernLeft, right: newKernRight, value: -50 }]);
                                    }
                                }, style: btnStyle(false), children: "Add Pair" })] }), jsx("div", { style: { maxHeight: 200, overflowY: "auto" }, children: kerningPairs.length === 0 ? (jsx("div", { style: { color: "#868e96", fontSize: 11, padding: 8, textAlign: "center" }, children: "No kerning pairs defined" })) : kerningPairs.map((kp, i) => (jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center", padding: "2px 0", fontSize: 11 }, children: [jsxs("span", { style: { minWidth: 40, textAlign: "center", fontSize: 16 }, children: [kp.left, kp.right] }), jsx("input", { type: "range", min: -200, max: 200, value: kp.value, onChange: e => setKerningPairs(prev => prev.map((p, j) => j === i ? { ...p, value: Number(e.target.value) } : p)), style: { flex: 1 } }), jsx("span", { style: { minWidth: 40, textAlign: "right" }, children: kp.value }), jsx("button", { onClick: () => setKerningPairs(prev => prev.filter((_, j) => j !== i)), style: { background: "transparent", border: "none", color: "#ff6b6b", cursor: "pointer" }, children: "\u2715" })] }, i))) })] })), jsxs("div", { style: { marginTop: 8, borderTop: "1px solid #373a40", paddingTop: 8 }, children: [jsx("div", { style: { fontSize: 11, color: "#868e96", marginBottom: 4 }, children: "Preview" }), jsx("input", { value: editor.previewText, onChange: e => editor.setPreviewText(e.target.value), style: { width: "100%", padding: "6px 8px", ...fieldStyle, fontSize: 12 } }), jsx("div", { style: { marginTop: 8, padding: 16, background: "#fff", color: "#212529", borderRadius: 6, fontSize: 24, fontFamily: "serif" }, children: editor.previewText })] })] }));
};

export { NiceFontEditor, exportToSvgFont, useFontEditor };
//# sourceMappingURL=NiceFontEditor.js.map
