# -*- coding: utf-8 -*-
r"""Repoe a POSICAO do brilho nos modelos que vieram do Arena.

    python tools/brilho_repor_posicao.py             mostra quais diferem
    python tools/brilho_repor_posicao.py --aplicar   corrige

Cada slot `Weapon_EnchantNN` traz 40 bytes de dados, e la dentro um float que diz a que
altura o efeito se cola a arma. Nos modelos que se copiaram do Arena vem a posicao DELE:

    adaga DSM_SET_01_DAGGER   nosso -3.00   arena 0.00

Com 0.00 o brilho da adaga aparecia no CHAO, aos pes do personagem, em vez de na lamina --
foi o que o jogador viu em 01/09. O `._RC` ser identico garante a malha, nao a escala a que
o efeito e ancorado.

Corrige-se copiando dos nossos originais (`.bak13`) os 40 bytes de dados de cada slot, MENOS
os primeiros 4, que sao o indice do efeito e tem de continuar a apontar para a lista nova.
"""
import argparse
import os
import re
import shutil
import struct

WEAPON = r"C:\Games\Axion\ResUnpak\Character\Weapon"


def slots(d):
    """[(off_dados, nome, dados40)] percorrendo os Weapon_EnchantNN."""
    out = []
    for m in re.finditer(rb"Weapon_Enchant(\d\d)", d):
        o = m.end()
        out.append((o, m.group().decode(), d[o:o + 40]))
    return out


def main() -> int:
    ap = argparse.ArgumentParser(description="Repoe a posicao do brilho nos modelos do Arena.")
    ap.add_argument("--aplicar", action="store_true")
    ap.add_argument("--modelo")
    args = ap.parse_args()

    alvos = ([args.modelo + "._OB"] if args.modelo
             else sorted(f for f in os.listdir(WEAPON) if f.endswith("._OB")))
    n_dif = n_ok = 0
    for f in alvos:
        cam = os.path.join(WEAPON, f)
        bak = cam + ".bak13"
        if not os.path.exists(bak):
            continue
        d, b = open(cam, "rb").read(), open(bak, "rb").read()
        sa, sb = slots(d), slots(b)
        if not sa or not sb:
            continue
        # so se corrige o que ha nos dois; os slots novos ficam com o do ultimo original
        pares = [(sa[i], sb[i if i < len(sb) else -1]) for i in range(len(sa))]
        difere = any(a[2][4:] != c[2][4:] for a, c in pares)
        if not difere:
            n_ok += 1
            continue
        n_dif += 1
        fa = struct.unpack_from("<f", sa[0][2], 20)[0]
        fb = struct.unpack_from("<f", sb[0][2], 20)[0]
        print("   %-28s agora %6.2f  ->  nosso %6.2f  (%d slots)"
              % (f[:-4], fa, fb, len(sa)))
        if not args.aplicar:
            continue
        saida = bytearray(d)
        for (off_a, _na, da), (_ob, _nb, db) in pares:
            saida[off_a + 4:off_a + 40] = db[4:40]
        open(cam, "wb").write(bytes(saida))
    print("\nmodelos com posicao diferente: %d | ja certos: %d" % (n_dif, n_ok))
    if not args.aplicar:
        print("nada gravado. junte --aplicar")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
