# -*- coding: utf-8 -*-
r"""Traz do Arena as linhas de atributo dos niveis de refino que nos faltam.

    python tools/importar_refino_alto.py            mostra
    python tools/importar_refino_alto.py --aplicar  insere em dbo.item_atributo

O PROBLEMA. Poe-se +18 num item e o client nao mostra nada. O refino chega la (byte 7 do
registo, medido), a tabela ItemEnchant ja tem os niveis 14 a 18 -- o que falta e a linha de
ATRIBUTOS desse nivel. A nossa dbo.item_atributo tem:

    +0 a +13   2247 itens em cada nivel
    +16          862 itens
    +14, +15, +17, +18   NENHUM

Sem linha, o client nao sabe que dano ou defesa a peca tem naquele grau, e nao a desenha.

O QUE ISTO FAZ. Le o itemAttr do client do Arena (51.198 linhas contra as nossas 34.359) e
insere APENAS as combinacoes (item, refino) que nos faltam, para itens que ja existem no
nosso catalogo.

SO ACRESCENTA, e a razao importa: o catalogo do Arena e MAIS CURTO que o nosso (15.569 itens
contra 19.806). Substituir a tabela apagaria 4.237 itens que so nos temos. Aqui nenhuma
linha existente e tocada.
"""
import argparse
import os
import struct
import sys

RAIZ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(RAIZ, "tools"))
sys.path.insert(0, os.path.join(RAIZ, "server"))
import lod_crypto as L                                              # noqa: E402
import db                                                           # noqa: E402

ARENA = r"C:\Games\Arena\ResUnpak\Interface\IE_Lod\itemAttr.lod_en"
ATTR_FIXO = 116


def atributos_do_arena():
    """(item_id, refino, estrela, 13 doubles) de cada linha do itemAttr deles."""
    # pular_zero=False, como o itembase faz: com o modo por omissao esta tabela
    # decifra a lixo (o total sai 3.976.234.551).
    d = L.decrypt_lod_stream(open(ARENA, "rb").read(), pular_zero=False, xor=L.XOR_ARENA)
    versao, total = struct.unpack_from("<II", d, 0)
    if versao != 20101118:
        raise SystemExit("assinatura inesperada: %d" % versao)
    pos = 8
    for _ in range(total):
        if pos + ATTR_FIXO > len(d):
            break
        item_id, refino, estrela = struct.unpack_from("<III", d, pos)
        vals = struct.unpack_from("<13d", d, pos + 12)
        pos += ATTR_FIXO
        for _s in range(2):
            if pos + 4 > len(d):
                break
            (t,) = struct.unpack_from("<I", d, pos)
            pos += 4 + t
        yield item_id, refino, estrela, vals


def main() -> int:
    ap = argparse.ArgumentParser(description="Niveis de refino altos, do Arena.")
    ap.add_argument("--aplicar", action="store_true")
    args = ap.parse_args()

    con = db._conectar()
    cur = con.cursor()
    cur.execute("SELECT item_id, refino FROM dbo.item_atributo")
    tenho = set((int(a), int(b)) for a, b in cur.fetchall())
    cur.execute("SELECT item_id FROM dbo.item")
    itens = set(int(r[0]) for r in cur.fetchall())
    print("ja temos %d linhas de atributo, %d itens no catalogo" % (len(tenho), len(itens)))

    novas, fora, por_nivel = [], 0, {}
    for item_id, refino, estrela, vals in atributos_do_arena():
        if (item_id, refino) in tenho:
            continue
        if item_id not in itens:
            fora += 1
            continue                    # item que so o Arena tem: nao inventa catalogo
        novas.append((item_id, refino, estrela, vals))
        por_nivel[refino] = por_nivel.get(refino, 0) + 1

    print("linhas do Arena que nos faltam: %d" % len(novas))
    print("   (ignoradas %d por serem de itens que nao temos)" % fora)
    print()
    for nv in sorted(por_nivel):
        print("   refino +%-3d %d itens" % (nv, por_nivel[nv]))

    if not args.aplicar:
        print()
        print("nada gravado. corra com --aplicar")
        return 0

    n = 0
    for item_id, refino, estrela, v in novas:
        cur.execute(
            "INSERT INTO dbo.item_atributo (item_id, refino, estrela, dano_min, dano_max, "
            "dano_mag_min, dano_mag_max, vel_ataque, alcance, defesa, defesa_mag, "
            "bonus8, bonus9, bonus10, bonus11, bonus12, efeito) "
            "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
            item_id, refino, estrela, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
            v[8], v[9], v[10], v[11], v[12], 0)
        n += 1
        if n % 2000 == 0:
            con.commit()
    con.commit()
    print()
    print("inseridas %d linhas" % n)
    return 0


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