'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var PixelEditor_module = require('./PixelEditor.module.css.js');
var index = require('../packages/ui/dist/index.js');
var spriteGeneratorCore = require('./spriteGeneratorCore.js');
var characterGeneratorPresets = require('./characterGeneratorPresets.js');
var buildingGeneratorPresets = require('./buildingGeneratorPresets.js');
var animalGeneratorPresets = require('./animalGeneratorPresets.js');

/* ════════════════════════════════════════════════════════════════
   INITIALIZATION
   ════════════════════════════════════════════════════════════════ */
let _initialized = false;
function ensureInitialized() {
    if (_initialized)
        return;
    _initialized = true;
    characterGeneratorPresets.initCharacterParts();
    buildingGeneratorPresets.initBuildingParts();
    animalGeneratorPresets.initAnimalParts();
}
/* ════════════════════════════════════════════════════════════════
   HELPERS
   ════════════════════════════════════════════════════════════════ */
function palettesToOptions(palettes) {
    return Object.entries(palettes).map(([id, colors]) => ({
        id,
        name: id.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
        colors,
    }));
}
const CHAR_CATEGORIES = [
    'head', 'hair', 'face', 'torso', 'arm', 'leg', 'hat', 'helmet', 'armor', 'cape', 'weapon', 'shield',
];
const BUILDING_CATEGORIES = [
    'foundation', 'wall', 'floor', 'roof', 'door', 'window', 'chimney', 'decoration',
];
const ANIMAL_CATEGORIES = [
    'animalHead', 'animalBody', 'animalLeg', 'animalTail', 'animalWing', 'animalMane',
];
const NiceSpriteGeneratorPanel = ({ onSendToCanvas, onClose, }) => {
    ensureInitialized();
    /* ── State ── */
    const [tab, setTab] = React.useState('character');
    const [selectedPresetIdx, setSelectedPresetIdx] = React.useState(0);
    const [selectedParts, setSelectedParts] = React.useState([]);
    const [canvasW, setCanvasW] = React.useState(32);
    const [canvasH, setCanvasH] = React.useState(32);
    const [direction, setDirection] = React.useState('S');
    const [projection, setProjection] = React.useState('topDown');
    const [generate8Dir, setGenerate8Dir] = React.useState(false);
    // Color overrides
    const [skinPalette, setSkinPalette] = React.useState('light');
    const [hairPalette, setHairPalette] = React.useState('brown');
    const [clothPalette, setClothPalette] = React.useState('leather');
    const [furPalette, setFurPalette] = React.useState('orange');
    const [wallPalette, setWallPalette] = React.useState('grey_stone');
    const [roofPalette, setRoofPalette] = React.useState('terracotta');
    const previewRef = React.useRef(null);
    const partsMapRef = React.useRef(new Map());
    /* ── Build parts map ── */
    React.useEffect(() => {
        const map = new Map();
        for (const p of spriteGeneratorCore.getAllParts())
            map.set(p.id, p);
        partsMapRef.current = map;
    }, []);
    /* ── Get presets for current tab ── */
    const presets = React.useMemo(() => {
        switch (tab) {
            case 'character': return characterGeneratorPresets.CHARACTER_PRESETS;
            case 'building': return buildingGeneratorPresets.BUILDING_PRESETS;
            case 'animal': return animalGeneratorPresets.ANIMAL_PRESETS;
        }
    }, [tab]);
    /* ── Apply preset ── */
    const applyPreset = React.useCallback((presetIdx) => {
        setSelectedPresetIdx(presetIdx);
        const preset = presets[presetIdx];
        if (!preset)
            return;
        if (tab === 'building') {
            const bp = preset;
            const assembly = buildingGeneratorPresets.assembleBuildingFromConfig(bp.config);
            setSelectedParts(assembly.parts);
            setCanvasW(assembly.canvasWidth);
            setCanvasH(assembly.canvasHeight);
        }
        else {
            const cp = preset;
            const assembly = cp.assembly;
            setSelectedParts([...assembly.parts]);
            setCanvasW(assembly.canvasWidth);
            setCanvasH(assembly.canvasHeight);
        }
    }, [tab, presets]);
    /* ── Initial preset ── */
    React.useEffect(() => {
        applyPreset(0);
    }, [tab, applyPreset]);
    /* ── Build current assembly ── */
    const currentAssembly = React.useMemo(() => {
        var _a;
        return ({
            id: `gen_${tab}_${selectedPresetIdx}`,
            name: ((_a = presets[selectedPresetIdx]) === null || _a === void 0 ? void 0 : _a.name) || 'Custom',
            parts: selectedParts,
            canvasWidth: canvasW,
            canvasHeight: canvasH,
            projection,
        });
    }, [tab, selectedPresetIdx, selectedParts, canvasW, canvasH, projection, presets]);
    /* ── Render preview ── */
    React.useEffect(() => {
        const canvas = previewRef.current;
        if (!canvas)
            return;
        const img = spriteGeneratorCore.assembleSprite(currentAssembly, partsMapRef.current, direction);
        let finalImg = img;
        if (projection === 'iso25d') {
            finalImg = spriteGeneratorCore.applyIsometricProjection(img);
        }
        canvas.width = finalImg.width;
        canvas.height = finalImg.height;
        const ctx = canvas.getContext('2d');
        if (ctx) {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.putImageData(finalImg, 0, 0);
        }
    }, [currentAssembly, direction, projection]);
    /* ── Toggle part visibility ── */
    const togglePart = React.useCallback((partId) => {
        setSelectedParts(prev => prev.map(p => { var _a; return p.partId === partId ? { ...p, visible: !((_a = p.visible) !== null && _a !== void 0 ? _a : true) } : p; }));
    }, []);
    /* ── Add part ── */
    const addPart = React.useCallback((partId) => {
        if (selectedParts.some(p => p.partId === partId))
            return;
        const part = spriteGeneratorCore.getPart(partId);
        if (!part)
            return;
        setSelectedParts(prev => {
            var _a, _b, _c, _d;
            return [...prev, {
                    partId,
                    offsetX: Math.floor(canvasW / 2) - Math.floor(((_b = (_a = part.pixels.S) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : 8) / 2),
                    offsetY: Math.floor(canvasH / 2) - Math.floor(((_d = (_c = part.pixels.S) === null || _c === void 0 ? void 0 : _c.height) !== null && _d !== void 0 ? _d : 8) / 2),
                    visible: true,
                }];
        });
    }, [selectedParts, canvasW, canvasH]);
    /* ── Remove part ── */
    const removePart = React.useCallback((partId) => {
        setSelectedParts(prev => prev.filter(p => p.partId !== partId));
    }, []);
    /* ── Send to canvas ── */
    const handleSendToCanvas = React.useCallback(() => {
        if (generate8Dir) {
            const frames = spriteGeneratorCore.generateAllDirections(currentAssembly, partsMapRef.current);
            const sheet = spriteGeneratorCore.render8DirSpriteSheet(frames);
            onSendToCanvas(sheet);
        }
        else {
            let img = spriteGeneratorCore.assembleSprite(currentAssembly, partsMapRef.current, direction);
            if (projection === 'iso25d') {
                img = spriteGeneratorCore.applyIsometricProjection(img);
            }
            onSendToCanvas(img);
        }
        onClose();
    }, [generate8Dir, currentAssembly, direction, projection, onSendToCanvas, onClose]);
    /* ── Categories for current tab ── */
    const categories = React.useMemo(() => {
        switch (tab) {
            case 'character': return CHAR_CATEGORIES;
            case 'building': return BUILDING_CATEGORIES;
            case 'animal': return ANIMAL_CATEGORIES;
        }
    }, [tab]);
    /* ── Available palette options ── */
    const paletteGroups = React.useMemo(() => {
        switch (tab) {
            case 'character': return [
                { label: 'Skin', options: palettesToOptions(characterGeneratorPresets.SKIN_PALETTES), value: skinPalette, set: setSkinPalette },
                { label: 'Hair', options: palettesToOptions(characterGeneratorPresets.HAIR_PALETTES), value: hairPalette, set: setHairPalette },
                { label: 'Clothing', options: palettesToOptions(characterGeneratorPresets.CLOTHING_PALETTES), value: clothPalette, set: setClothPalette },
            ];
            case 'building': return [
                { label: 'Walls', options: palettesToOptions(buildingGeneratorPresets.WALL_PALETTES), value: wallPalette, set: setWallPalette },
                { label: 'Roof', options: palettesToOptions(buildingGeneratorPresets.ROOF_PALETTES), value: roofPalette, set: setRoofPalette },
            ];
            case 'animal': return [
                { label: 'Fur', options: palettesToOptions(animalGeneratorPresets.FUR_PALETTES), value: furPalette, set: setFurPalette },
            ];
        }
    }, [tab, skinPalette, hairPalette, clothPalette, wallPalette, roofPalette, furPalette]);
    /* ── Render ── */
    return (jsxRuntime.jsx(index.NiceModal, { open: true, onClose: onClose, title: "Sprite Generator", children: jsxRuntime.jsxs("div", { className: PixelEditor_module.genPanel, children: [jsxRuntime.jsxs("div", { className: PixelEditor_module.genHeader, children: [jsxRuntime.jsx("h3", { children: "Sprite Generator" }), jsxRuntime.jsx(index.NiceButton, { className: PixelEditor_module.btnIcon, variant: "ghost", size: "sm", onClick: onClose, title: "Close", children: "\u2715" })] }), jsxRuntime.jsx("div", { className: PixelEditor_module.genTabs, children: ['character', 'building', 'animal'].map(t => (jsxRuntime.jsxs(index.NiceButton, { className: `${PixelEditor_module.genTabBtn} ${tab === t ? PixelEditor_module.genTabBtnActive : ''}`, variant: tab === t ? 'primary' : 'ghost', size: "sm", onClick: () => setTab(t), children: [t === 'character' ? '🧑' : t === 'building' ? '🏠' : '🐾', ' ', t.charAt(0).toUpperCase() + t.slice(1)] }, t))) }), jsxRuntime.jsxs("div", { className: PixelEditor_module.genBody, children: [jsxRuntime.jsxs("div", { className: PixelEditor_module.genLeft, children: [jsxRuntime.jsxs("div", { className: PixelEditor_module.panelSection, children: [jsxRuntime.jsx("div", { className: PixelEditor_module.panelTitle, children: jsxRuntime.jsx("span", { children: "Presets" }) }), jsxRuntime.jsx("div", { className: PixelEditor_module.genPresetGrid, children: presets.map((preset, i) => (jsxRuntime.jsx(index.NiceButton, { className: `${PixelEditor_module.genPresetBtn} ${i === selectedPresetIdx ? PixelEditor_module.genPresetBtnActive : ''}`, variant: i === selectedPresetIdx ? 'primary' : 'ghost', size: "sm", onClick: () => applyPreset(i), title: preset.name, children: preset.name }, i))) })] }), jsxRuntime.jsxs("div", { className: PixelEditor_module.panelSection, style: { flex: 1, overflowY: 'auto' }, children: [jsxRuntime.jsx("div", { className: PixelEditor_module.panelTitle, children: jsxRuntime.jsx("span", { children: "Parts" }) }), categories.map(cat => {
                                            const parts = spriteGeneratorCore.getPartsByCategory(cat);
                                            if (parts.length === 0)
                                                return null;
                                            return (jsxRuntime.jsxs("div", { style: { marginBottom: 6 }, children: [jsxRuntime.jsx("div", { style: { fontSize: 9, color: 'var(--gray-600)', marginBottom: 2, textTransform: 'uppercase' }, children: cat.replace(/([A-Z])/g, ' $1').trim() }), jsxRuntime.jsx("div", { className: PixelEditor_module.genPartGrid, children: parts.map(part => {
                                                            const active = selectedParts.some(p => { var _a; return p.partId === part.id && ((_a = p.visible) !== null && _a !== void 0 ? _a : true); });
                                                            return (jsxRuntime.jsx(index.NiceButton, { className: `${PixelEditor_module.miniBtn} ${active ? PixelEditor_module.miniBtnActive : ''}`, variant: active ? 'primary' : 'ghost', size: "sm", onClick: () => active ? removePart(part.id) : addPart(part.id), title: part.name, children: part.name.slice(0, 8) }, part.id));
                                                        }) })] }, cat));
                                        })] })] }), jsxRuntime.jsxs("div", { className: PixelEditor_module.genCenter, children: [jsxRuntime.jsx("div", { className: PixelEditor_module.genPreviewWrap, children: jsxRuntime.jsx("canvas", { ref: previewRef, className: PixelEditor_module.genPreviewCanvas }) }), jsxRuntime.jsx("div", { className: PixelEditor_module.genDirGrid, children: spriteGeneratorCore.ALL_DIRECTIONS.map(d => (jsxRuntime.jsx(index.NiceButton, { className: `${PixelEditor_module.miniBtn} ${direction === d ? PixelEditor_module.miniBtnActive : ''}`, variant: direction === d ? 'primary' : 'ghost', size: "sm", onClick: () => setDirection(d), children: d }, d))) }), jsxRuntime.jsxs("div", { className: PixelEditor_module.genRow, children: [jsxRuntime.jsx("label", { style: { fontSize: 10, color: 'var(--gray-600)' }, children: "Projection" }), jsxRuntime.jsx(index.NiceSelect, { className: PixelEditor_module.propSelect, value: projection, onChange: val => setProjection(val), options: [
                                                { value: 'topDown', label: 'Top-Down' },
                                                { value: 'sideView', label: 'Side View' },
                                                { value: 'iso25d', label: '2.5D Isometric' },
                                            ] })] }), jsxRuntime.jsxs("div", { className: PixelEditor_module.genRow, children: [jsxRuntime.jsx("label", { style: { fontSize: 10, color: 'var(--gray-600)' }, children: "Size" }), jsxRuntime.jsx(index.NiceNumberInput, { className: PixelEditor_module.propInput, style: { width: 48 }, min: 8, max: 256, value: canvasW, onChange: val => setCanvasW(val !== null && val !== void 0 ? val : 32) }), jsxRuntime.jsx("span", { style: { fontSize: 10, color: 'var(--gray-600)' }, children: "\u00D7" }), jsxRuntime.jsx(index.NiceNumberInput, { className: PixelEditor_module.propInput, style: { width: 48 }, min: 8, max: 256, value: canvasH, onChange: val => setCanvasH(val !== null && val !== void 0 ? val : 32) })] }), jsxRuntime.jsx(index.NiceCheckbox, { checked: generate8Dir, onChange: checked => setGenerate8Dir(checked), label: "Generate 8-direction sheet", className: PixelEditor_module.checkLabel })] }), jsxRuntime.jsxs("div", { className: PixelEditor_module.genRight, children: [jsxRuntime.jsxs("div", { className: PixelEditor_module.panelSection, children: [jsxRuntime.jsx("div", { className: PixelEditor_module.panelTitle, children: jsxRuntime.jsx("span", { children: "Colors" }) }), paletteGroups.map(group => {
                                            var _a;
                                            return (jsxRuntime.jsxs("div", { style: { marginBottom: 6 }, children: [jsxRuntime.jsx("div", { style: { fontSize: 9, color: 'var(--gray-600)', marginBottom: 2 }, children: group.label }), jsxRuntime.jsx(index.NiceSelect, { className: PixelEditor_module.propSelect, value: group.value, onChange: val => group.set(val), options: group.options.map(opt => ({ value: opt.id, label: opt.name })) }), jsxRuntime.jsx("div", { className: PixelEditor_module.genColorSwatches, children: (_a = group.options.find(o => o.id === group.value)) === null || _a === void 0 ? void 0 : _a.colors.map((c, i) => (jsxRuntime.jsx("div", { className: PixelEditor_module.genColorSwatch, style: { backgroundColor: c }, title: c }, i))) })] }, group.label));
                                        })] }), jsxRuntime.jsxs("div", { className: PixelEditor_module.panelSection, style: { flex: 1, overflowY: 'auto' }, children: [jsxRuntime.jsx("div", { className: PixelEditor_module.panelTitle, children: jsxRuntime.jsx("span", { children: "Assembly" }) }), selectedParts.map((ap, i) => {
                                            var _a, _b, _c, _d;
                                            const part = partsMapRef.current.get(ap.partId);
                                            return (jsxRuntime.jsxs("div", { className: PixelEditor_module.genAssemblyItem, children: [jsxRuntime.jsx(index.NiceButton, { className: PixelEditor_module.btnIcon, variant: "ghost", size: "sm", onClick: () => togglePart(ap.partId), title: ((_a = ap.visible) !== null && _a !== void 0 ? _a : true) ? 'Hide' : 'Show', children: ((_b = ap.visible) !== null && _b !== void 0 ? _b : true) ? '👁' : '─' }), jsxRuntime.jsx("span", { className: PixelEditor_module.genAssemblyName, children: (_c = part === null || part === void 0 ? void 0 : part.name) !== null && _c !== void 0 ? _c : ap.partId }), jsxRuntime.jsxs("span", { style: { fontSize: 9, color: 'var(--gray-700)' }, children: ["z:", (_d = part === null || part === void 0 ? void 0 : part.zOrder) !== null && _d !== void 0 ? _d : 0] }), jsxRuntime.jsx(index.NiceButton, { className: PixelEditor_module.btnIcon, variant: "ghost", size: "sm", onClick: () => removePart(ap.partId), title: "Remove", children: "\u2715" })] }, ap.partId));
                                        })] })] })] }), jsxRuntime.jsxs("div", { className: PixelEditor_module.genFooter, children: [jsxRuntime.jsx(index.NiceButton, { className: PixelEditor_module.btnSecondary, variant: "ghost", onClick: onClose, children: "Cancel" }), jsxRuntime.jsx(index.NiceButton, { className: PixelEditor_module.btnPrimary, variant: "primary", onClick: handleSendToCanvas, children: "\uD83D\uDCCB Send to Canvas" })] })] }) }));
};
NiceSpriteGeneratorPanel.displayName = 'NiceSpriteGeneratorPanel';

module.exports = NiceSpriteGeneratorPanel;
//# sourceMappingURL=SpriteGeneratorPanel.js.map
