// renderer.js : projection iso (world -> screen et inverse), camera, projectiles + AOE
// formule : sx = (wx - wy) * tw/2  /  sy = (wx + wy) * th/2

import { Graphics } from 'pixi.js';

import {
    ARENA_WIDTH, ARENA_HEIGHT,
    TILE_WIDTH, TILE_HEIGHT,
    PROJECTILE_HIT_RADIUS, SOULGATE_HITBOX_RADIUS,
    SOULGATE_X, SOULGATE_Y,
} from './constants.js';

let _debugHitboxes = false;
export function setDebugHitboxes(v) { _debugHitboxes = v; }

// Re-exports : ces fonctions viennent d'autres fichiers mais sont exposées ici
// → main.js peut tout importer depuis renderer.js en un seul endroit
export { drawStaticArena } from './renderArena.js';   // dessine l'arène statique (sol, Soulgate, etc.)
export { updateEnemies }   from './renderEnemies.js'; // met à jour les sprites ennemis
export { updatePlayers }   from './renderPlayers.js'; // met à jour les sprites joueurs


// Zoom / Layout

// Nombre d'unités monde visibles en diagonale iso — détermine le niveau de zoom
// Plus c'est grand → plus on voit loin → plus les objets sont petits
const CAMERA_VIEWPORT_DIAG = 22;

// tw / th = pixels par "unité monde" dans les axes X et Y isométriques
// recalcules au resize
let tw, th;

export function getTh() { return th; }
export function getTw() { return tw; }


export function updateIsoLayout(screenW, screenH) {
    const bW = CAMERA_VIEWPORT_DIAG * TILE_WIDTH  / 2;
    const bH = CAMERA_VIEWPORT_DIAG * TILE_HEIGHT / 2;
    tw = TILE_WIDTH  * (screenW / bW);
    th = TILE_HEIGHT * (screenH / bH);
}


// projection iso : (wx - wy) * tw/2  /  (wx + wy) * th/2
export function iso(wx, wy) {
    return {
        x: (wx - wy) * tw / 2,
        y: (wx + wy) * th / 2,
    };
}


export function screenToWorld(screenX, screenY, containerX, containerY) {
    // inverse de iso, sert au clic souris
    const sx = screenX - containerX;
    const sy = screenY - containerY;
    return {
        wx: sx / tw + sy / th,
        wy: sy / th - sx / tw,
    };
}


export function updateCamera(worldContainer, screenW, screenH, wx, wy) {
    const HW = ARENA_WIDTH  / 2;
    const HH = ARENA_HEIGHT / 2;
    // clamp pour pas voir du vide au bord
    const camX = Math.max(-HW, Math.min(HW, wx));
    const camY = Math.max(-HH, Math.min(HH, wy));

    const p = iso(camX, camY);
    worldContainer.x = screenW / 2 - p.x;
    worldContainer.y = screenH / 2 - p.y;
}


export function updateProjectiles(layer, pool, projectiles) {
    const ids = new Set(projectiles.map(p => p.id));
    for (const [id, g] of Object.entries(pool)) {
        if (!ids.has(id)) {
            layer.removeChild(g);
            delete pool[id];
        }
    }

    for (const p of projectiles) {
        if (!pool[p.id]) {
            pool[p.id] = _createProjectileGraphic();
            layer.addChild(pool[p.id]);
        }
        const pos = iso(p.x, p.y);
        pool[p.id].x = pos.x;
        pool[p.id].y = pos.y;

        // Debug : hitbox du projectile
        if (_debugHitboxes && pool[p.id]._hboxG) {
            const hg = pool[p.id]._hboxG;
            hg.clear();
            const rx = PROJECTILE_HIT_RADIUS * tw / 2;
            const ry = PROJECTILE_HIT_RADIUS * th / 2;
            hg.ellipse(0, 0, rx, ry).stroke({ color: 0xffff00, width: 1, alpha: 0.8 });
        } else if (!_debugHitboxes && pool[p.id]._hboxG) {
            pool[p.id]._hboxG.clear();
        }
    }
}


function _createProjectileGraphic() {
    const g = new Graphics();
    const r = Math.max(3, th * 0.08);
    g.circle(0, 0, r).fill({ color: 0xffee44 });
    g.circle(0, 0, r).stroke({ color: 0xffffff, width: 1, alpha: 0.3 });

    // sous-graphics pour la hitbox debug
    const hboxG = new Graphics();
    g.addChild(hboxG);
    g._hboxG = hboxG;

    return g;
}


// AOE

const _AOE_STYLE = {
    slam:  { fill: 0xff6600, stroke: 0xffaa44 },
    storm: { fill: 0x8800ff, stroke: 0xcc88ff },
    void:  { fill: 0x00ccff, stroke: 0x88eeff },
    pulse: { fill: 0xffd700, stroke: 0xfff0a0 },
};

export function updateAoeZones(layer, pool, zones) {
    // Supprimer les zones disparues
    const ids = new Set(zones.map(z => z.id));
    for (const [id, g] of Object.entries(pool)) {
        if (!ids.has(id)) { layer.removeChild(g); delete pool[id]; }
    }

    for (const z of zones) {
        if (!pool[z.id]) {
            pool[z.id] = new Graphics();
            layer.addChild(pool[z.id]);
        }
        const g = pool[z.id];
        const pos = iso(z.x, z.y);
        g.x = pos.x;
        g.y = pos.y;

        const progress = z.ticks / z.max_ticks;   // 1.0 → 0.0 au fil du temps
        const pal = _AOE_STYLE[z.type] ?? _AOE_STYLE.slam;
        const rx  = z.radius * tw / 2;
        const ry  = z.radius * th / 2;

        g.clear();
        g.ellipse(0, 0, rx, ry).fill({ color: pal.fill,   alpha: 0.18 * progress });
        g.ellipse(0, 0, rx, ry).stroke({ color: pal.stroke, width: 2, alpha: 0.85 * progress });
    }
}


// hitbox debug Soulgate (plus utilise mais on garde le graphics au cas ou)

let _sgHboxG = null;

export function initSoulgateHitbox(layer) {
    if (_sgHboxG) { layer.removeChild(_sgHboxG); }
    _sgHboxG = new Graphics();
    layer.addChild(_sgHboxG);
}

export function updateSoulgateHitbox() {
    if (!_sgHboxG) return;
    _sgHboxG.clear();
    if (_debugHitboxes) {
        const pos = iso(SOULGATE_X, SOULGATE_Y);
        _sgHboxG.x = pos.x;
        _sgHboxG.y = pos.y;
        const rx = SOULGATE_HITBOX_RADIUS * tw / 2;
        const ry = SOULGATE_HITBOX_RADIUS * th / 2;
        _sgHboxG.ellipse(0, 0, rx, ry).stroke({ color: 0x00ff88, width: 2, alpha: 0.9 });
    }
}
