// tiledLoader.js : charge une map Tiled (.tmj + .tsx) et la dessine en iso

import { Sprite, Assets } from 'pixi.js';
import { iso, getTw, getTh } from './renderer.js';


export async function loadTiledMap(mapPath) {
    // baseUrl = dossier du .tmj (les .tsx sont a cote)
    const baseUrl = mapPath.substring(0, mapPath.lastIndexOf('/') + 1);
    const map = await fetch(mapPath).then(r => r.json());

    // parse les .tsx (XML) referencements (firstgid + chemin image par tile id)
    const tilesets = [];
    for (const ts of map.tilesets) {
        const tsxText = await fetch(baseUrl + ts.source).then(r => r.text());
        const xml = new DOMParser().parseFromString(tsxText, 'text/xml');
        const tiles = {};
        for (const tile of xml.querySelectorAll('tile')) {
            const id = parseInt(tile.getAttribute('id'));
            const img = tile.querySelector('image');
            if (img) {
                tiles[id] = {
                    src: baseUrl + img.getAttribute('source'),
                    w:   parseInt(img.getAttribute('width')),
                    h:   parseInt(img.getAttribute('height')),
                };
            }
        }
        tilesets.push({ firstgid: ts.firstgid, tiles });
    }

    // precharger toutes les textures
    const urls = [];
    for (const ts of tilesets) {
        for (const id in ts.tiles) urls.push(ts.tiles[id].src);
    }
    await Assets.load(urls);

    return { map, tilesets };
}


function _gidToTile(gid, tilesets) {
    // chercher dans le bon tileset (firstgid descendant)
    for (let i = tilesets.length - 1; i >= 0; i--) {
        if (gid >= tilesets[i].firstgid) {
            return tilesets[i].tiles[gid - tilesets[i].firstgid] || null;
        }
    }
    return null;
}


export function drawTiledMap(layer, data) {
    const { map, tilesets } = data;
    const W = map.width;
    const H = map.height;
    const tw = getTw();
    const th = getTh();

    // reference : la base (footprint iso) d'un sprite Kenney fait 256x128 px
    // au tw courant, on veut que cette base remplisse 1 unite monde (tw x th px)
    const REF_TILE_W = 256;
    const scale = tw / REF_TILE_W;

    for (const tlayer of map.layers) {
        if (tlayer.type !== 'tilelayer') continue;
        if (tlayer.visible === false) continue;

        for (let i = 0; i < tlayer.data.length; i++) {
            const gid = tlayer.data[i];
            if (gid === 0) continue;  // 0 = case vide

            const tile = _gidToTile(gid, tilesets);
            if (!tile) continue;

            const col = i % W;
            const row = Math.floor(i / W);
            // centrer la map sur (0, 0)
            const wx = col - (W - 1) / 2;
            const wy = row - (H - 1) / 2;

            const tex = Assets.get(tile.src);
            if (!tex) continue;

            const sprite = new Sprite(tex);
            sprite.anchor.set(0.5, 1.0);  // base centree sur la tile, le sprite "monte"
            const p = iso(wx, wy);
            sprite.x = p.x;
            sprite.y = p.y + th / 2;  // decalage half pour que la pointe basse de la diamond touche la base
            sprite.scale.set(scale);
            layer.addChild(sprite);
        }
    }
}
