# -*- coding: utf-8 -*-
r"""Procura valores em TODAS as tabelas .lod do client, de uma passagem so.

    python tools/buscar_nos_lod.py 30000300 1004 328

Decifra cada ficheiro UMA vez por modo e procura todos os alvos ao mesmo tempo, em
u32 LE, u16 LE, float32 e double. A versao ingenua -- um ficheiro por valor -- levava
mais de dois minutos por valor, porque a decifragem e o caro.
"""
import glob
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 lod_crypto                                                   # noqa: E402
import itembase                                                     # noqa: E402


def moldes(v):
    """As formas que um numero pode ter no ficheiro."""
    saida = []
    n = int(v)
    if 0 <= n < 2 ** 32:
        saida.append(("u32", struct.pack("<I", n)))
    if 0 <= n < 2 ** 16:
        saida.append(("u16", struct.pack("<H", n)))
    saida.append(("f32", struct.pack("<f", float(v))))
    saida.append(("f64", struct.pack("<d", float(v))))
    return saida


def main() -> int:
    alvos = [float(a) if "." in a else int(a) for a in sys.argv[1:]]
    if not alvos:
        print(__doc__.strip().splitlines()[2])
        return 1
    procura = {a: moldes(a) for a in alvos}
    caminhos = sorted(glob.glob(os.path.join(itembase.BASE, "*.lod*")))
    print("%d ficheiros, %d valores" % (len(caminhos), len(alvos)))
    for cam in caminhos:
        bruto = open(cam, "rb").read()
        vistos = set()
        for pz in (True, False):
            try:
                d = lod_crypto.decrypt_lod_stream(bruto, pular_zero=pz)
            except Exception:
                continue
            if d in vistos:
                continue
            vistos.add(d)
            for a, ms in procura.items():
                for tipo, pat in ms:
                    if len(pat) < 4:            # u16 da falso positivo demais
                        continue
                    c = d.count(pat)
                    if c:
                        off = d.find(pat)
                        print("   %-28s pz=%-5s %-4s %-12s %3d x, 1o em %d"
                              % (os.path.basename(cam), pz, tipo, a, c, off))
    return 0


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