# -*- coding: utf-8 -*-
"""Importa a combinacao de equipamento do client para Data/Items/ItemCombination.ini.

    python tools/importar_combinacao.py            mostra
    python tools/importar_combinacao.py --aplicar  grava

DE ONDE VEM

ItemCombEqui.lod, pular_zero=True. Cabecalho de 4 bytes e registos de 28, sete u32:

    [0:4]   item_id            2672 de 2672 sao itens do catalogo
    [4:8]   nivel              0 a 13, catorze linhas por item
    [8:12]  efeito             sobe de um em um a cada nivel, e continua a contar
                               no item seguinte (60532..60545, depois 60546..)
    [12:16] custo_a            \ dois custos, constantes dentro do mesmo item
    [16:20] custo_b            /
    [20:24] material           99996 em TODOS -- "Extrato de vroquiana"
    [24:28] grau               constante por item, so 12 valores em toda a tabela

Sao 202 itens. Doze deles tem menos de catorze niveis.

O QUE E MEDIDO E O QUE E PALPITE

Medido: o item, o nivel, e que o material e sempre o mesmo. Que custo_a, custo_b e grau nao
mudam entre niveis do mesmo item -- verificado nos 202.

Palpite, e por isso os nomes sao neutros: que custo_a e custo_b sejam mesmo custos. Sobem
com a qualidade do item (12000/40000 na Espada de Duas Maos, 60000/200000 na do cavaleiro),
o que e coerente, mas nada no ficheiro o diz. O `grau` idem -- vale 7 na espada basica e 20
na do cavaleiro, e podia ser grau, tempo ou probabilidade.

Preferi nome neutro a nome bonito: uma coluna chamada `custo_alz` que afinal fosse tempo
seria pior do que uma chamada `custo_a` que obriga quem a usar a confirmar primeiro.

PISTA POR SEGUIR

Os ids de efeito 605xx sao vizinhos dos 60204 e 60241 das pericias de conjunto, que estao no
skillData.lod. E a mesma gama de numeracao: descobrir o que a 60204 faz provavelmente
resolve a 60532 tambem.
"""
import collections
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, "server"))
sys.path.insert(0, os.path.join(RAIZ, "tools"))
import data_files as D                                              # noqa: E402
import lod_crypto                                                   # noqa: E402

LOD = r"C:\Games\Karos\ResUnpak\Interface\IE_Lod\ItemCombEqui.lod_pt"
TAM, CAB = 28, 4
TAB = chr(9)
CR = chr(13) + chr(10)


def ler():
    d = lod_crypto.decrypt_lod_stream(open(LOD, "rb").read())
    n = struct.unpack_from("<I", d, 0)[0]
    saida = []
    for k in range(n):
        off = CAB + k * TAM
        if off + TAM > len(d):
            break
        saida.append(struct.unpack_from("<7I", d, off))
    return saida


def main() -> int:
    aplicar = "--aplicar" in sys.argv
    D.carregar()
    itens = {r["item_id"]: str(r.get("nome") or "?") for r in D.tabela("Item")}
    regs = ler()

    por_item = collections.Counter(r[0] for r in regs)
    materiais = collections.Counter(r[5] for r in regs)
    print("registos: %d | itens distintos: %d" % (len(regs), len(por_item)))
    print("materiais usados: %s" % [(m, itens.get(m, "?")) for m in materiais])
    print("itens sem os 14 niveis: %d" % sum(1 for v in por_item.values() if v != 14))
    print()
    print("%-9s %-30s %-7s %-9s %-9s %s" % ("item", "nome", "niveis", "custo_a", "custo_b", "grau"))
    vistos = set()
    for r in regs:
        if r[0] in vistos:
            continue
        vistos.add(r[0])
        if len(vistos) > 12:
            break
        print("%-9d %-30s %-7d %-9d %-9d %d"
              % (r[0], itens.get(r[0], "?")[:30], por_item[r[0]], r[3], r[4], r[6]))

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

    destino = os.path.join(RAIZ, "server", "Data", "Items", "ItemCombination.ini")
    cols = ["item_id", "nivel", "efeito", "custo_a", "custo_b", "material", "grau", "nome"]
    with open(destino, "w", encoding="utf-8", newline="") as fp:
        w = fp.write
        for l in [
            "; ItemCombination -- combinar equipamento, do ItemCombEqui.lod do client.",
            ";",
            "; 202 itens, catorze niveis cada (0 a 13). O material e o mesmo em todos os 2672",
            "; registos: 99996, 'Extrato de vroquiana'.",
            ";",
            "; MEDIDO: item, nivel, efeito e material. Que custo_a, custo_b e grau sao",
            "; constantes dentro do mesmo item -- conferido nos 202.",
            ";",
            "; PALPITE, e por isso os nomes sao neutros: que custo_a e custo_b sejam custos.",
            "; Sobem com a qualidade do item (12000/40000 na Espada de Duas Maos, 60000/200000",
            "; na do cavaleiro), o que e coerente, mas nada no ficheiro o diz. O `grau` idem.",
            ";",
            "; Chamar-lhes custo_a e custo_b obriga quem os usar a confirmar primeiro. Um nome",
            "; bonito que estivesse errado seria pior: passaria por facto.",
            ";",
            "; O efeito sobe de um em um a cada nivel e continua a contar no item seguinte.",
            "; Os ids 605xx sao vizinhos dos 60204/60241 das pericias de conjunto no",
            "; skillData.lod -- provavelmente o mesmo mecanismo.",
            "",
        ]:
            w(l + CR)
        w("//" + TAB.join(cols) + CR)
        for r in regs:
            nome = itens.get(r[0], "")
            celulas = [str(r[0]), str(r[1]), str(r[2]), str(r[3]), str(r[4]), str(r[5]),
                       str(r[6]), (chr(34) + nome + chr(34)) if " " in nome else nome]
            w(TAB.join(celulas) + CR)

    D.carregar()
    t = D.tabela("ItemCombination")
    print()
    print("gravado: %s (%s bytes)" % (destino, "{:,}".format(os.path.getsize(destino))))
    print("relido pelo servidor: %d linhas, colunas %s" % (len(t), list(t[0].keys())))
    return 0


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