// sprites-loader.js

const INDEX_PATH = './library/loader/tiny_swords.json';

const Sprites = {
    isLoaded: false,
    preloadAll,
};

async function preloadAll() {
    // 1. Charge le JSON unique (avec "sprites": [ ... ])
    const res = await fetch(INDEX_PATH);
    const data = await res.json();
    const allSprites = Array.isArray(data.sprites) ? data.sprites : [];

    // 2. Précharge toutes les images
    const images = {};
    const imagePromises = [];
    for (const sprite of allSprites) {
        if (!images[sprite.image]) {
            images[sprite.image] = new window.Image();
            images[sprite.image].src = "library/" + sprite.image;
            imagePromises.push(new Promise(resolve => {
                images[sprite.image].onload = () => resolve();
            }));
        }
    }
    await Promise.all(imagePromises);

    // 3. Génère l’arborescence de l’API Sprites
    for (const sprite of allSprites) {
        const category = sprite.category || 'uncategorized';
        if (!Sprites[category]) Sprites[category] = {};
        const key = sprite.name || (sprite.class ? `${sprite.class}_${sprite.color || ''}` : 'unknown');
        if (!Sprites[category][key]) Sprites[category][key] = {};

        if (sprite.type === 'animated') {
            for (const anim of sprite.animations) {
                Sprites[category][key][anim.name] = makeAnimationHelper(
                    images[sprite.image],
                    sprite,
                    anim,
                    sprite.size
                );
            }
            Sprites[category][key]._frames = sprite.frames;
        } else if (sprite.type === 'static') {
            for (const frame of sprite.frames) {
                Sprites[category][key][frame.name] = makeStaticHelper(
                    images[sprite.image],
                    frame,
                    sprite.size
                );
            }
            Sprites[category][key].drawDefault = (ctx, x, y, opts = {}) => {
                const frames = sprite.default.frames || [sprite.default.frame];
                for (const fname of frames) {
                    const f = sprite.frames.find(f => f.name === fname);
                    if (f) makeStaticHelper(images[sprite.image], f, sprite.size)(ctx, x, y, opts);
                }
            };
            Sprites[category][key]._frames = sprite.frames;
        }
    }
    Sprites.isLoaded = true;
}

// Helpers
function makeAnimationHelper(img, sprite, anim, size) {
    const frameObjs = anim.frames.map(fname => sprite.frames.find(f => f.name === fname));
    let frameIdx = 0, lastTime = 0;
    let lastDrawAnimName = '';
    return function draw(ctx, x, y, opts = {}) {
        if (draw !== lastDrawAnimName) {
            frameIdx = 0;
            lastTime = performance.now();
            lastDrawAnimName = draw;
        }
        const fps = opts.fps || 12;
        const now = performance.now();
        if (now - lastTime > 1000 / fps) {
            frameIdx = (frameIdx + 1) % frameObjs.length;
            lastTime = now;
        }
        const f = frameObjs[frameIdx];
        ctx.save();
        if (opts.flipX || opts.flipY) {
            ctx.translate(
                x + (opts.flipX ? (opts.w || size.w) : 0),
                y + (opts.flipY ? (opts.h || size.h) : 0)
            );
            ctx.scale(opts.flipX ? -1 : 1, opts.flipY ? -1 : 1);
            ctx.drawImage(
                img,
                f.x, f.y, size.w, size.h,
                0, 0, opts.w || size.w, opts.h || size.h
            );
        } else {
            ctx.drawImage(
                img,
                f.x, f.y, size.w, size.h,
                x, y, opts.w || size.w, opts.h || size.h
            );
        }
        ctx.restore();
    };
}

function makeStaticHelper(img, frame, size) {
    return function draw(ctx, x, y, opts = {}) {
        ctx.save();
        if (opts.flipX || opts.flipY) {
            ctx.translate(
                x + (opts.flipX ? (opts.w || size.w) : 0),
                y + (opts.flipY ? (opts.h || size.h) : 0)
            );
            ctx.scale(opts.flipX ? -1 : 1, opts.flipY ? -1 : 1);
            ctx.drawImage(
                img,
                frame.x, frame.y, size.w, size.h,
                0, 0, opts.w || size.w, opts.h || size.h
            );
        } else {
            ctx.drawImage(
                img,
                frame.x, frame.y, size.w, size.h,
                x, y, opts.w || size.w, opts.h || size.h
            );
        }
        ctx.restore();
    };
}

// Export en module ES ou global window
if (typeof window !== "undefined") window.Sprites = Sprites;
export default Sprites;