#!/usr/bin/env python3
"""Lleva al repo las glosas donde el impreso dice otra cosa.

De donde salen. `glosas_impreso.py` lee las parejas «clave—glosa» de los dos
lados y las empareja por posicion. De 234 diferencias, 149 son ruido de OCR y
85 son texto distinto de verdad. De esas 85 se aplican las que el impreso
sostiene sin dudas.

Regla del proyecto: manda el impreso, incluso cuando trae una errata evidente.
La excepcion es cuando la lectura del OCR es la sospechosa, no el papel.

Lo que NO se aplica, y por que:

  · glosa cortada por el OCR — el impreso dice menos porque el escaneo perdio
    el final, no porque el libro lo omita: «the entire purport of renunciation»
    leido «the entire», «Dakṣa, Marīci, Manu, etc» leido «daksa». Se detecta
    solo: lo impreso es principio exacto de lo del repo.

  · lectura absurda — «sarasvatī—the godless of learning» no lo imprimio nadie;
    es «goddess» con la dd leida como dl. Cuando el escaneo dice algo que no
    significa nada y ademas se parece a la del repo letra a letra, el
    sospechoso es el OCR. Van en DUDOSAS, con la pagina pendiente de mirar.

Uso:
    python3 aplicar_glosas.py                 # ensayo
    python3 aplicar_glosas.py --aplicar
"""
import json
import pathlib
import re
import sys
import unicodedata

HERE = pathlib.Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
from arbitrar_deriva import REPO  # noqa: E402

# Casos en que el sospechoso es el OCR y no el papel. Necesitan la imagen de la
# pagina; se dejan anotados para no volver a adjudicarlos a ciegas.
DUDOSAS = {
    ('sb-2.4.22.md', 'sarasvatī'): 'the goddess of learning: «godless» es «goddess» mal leido',
    ('sb-1.16.19.md', 'anāmayam'): '«hail and hearty» por «hale and hearty»: confusion de OCR',
    ('sb-1.14.19.md', 'aśru-mukhāḥ'): 'aśru es lagrima; «fearful» por «tearful» es t leida f',
    ('sb-1.19.32.md', 'atithi-rūpeṇa'): 'atithi es huesped; «the great» no cuadra con la traduccion',
    ('cc-adi-17.207.md', 'mṛdaṅga'): 'el impreso pierde «drum», puede ser corte de linea',
    ('cc-adi-9.23.md', 'upaśākhā'): 'el impreso pierde «again» al principio, no al final',
    ('cc-antya-6.232.md', 'kara upadeśa'): '«please instructions» no es ingles: falta «give»',
}


def pel(s):
    s = str(s or '').replace('*', '')
    s = ''.join(c for c in unicodedata.normalize('NFD', s) if not unicodedata.combining(c))
    return re.sub(r'\s+', ' ', re.sub(r"[^a-zA-Z' ]", ' ', s)).strip().lower()


def truncada(repo, imp):
    """¿Es lo impreso el principio de lo del repo? Entonces falta texto, no sobra."""
    a, b = pel(repo).split(), pel(imp).split()
    return len(b) < len(a) and a[:len(b)] == b


def rehacer(glosa_vieja, glosa_impresa):
    """La glosa del impreso, respetando mayusculas y diacriticos del repo.

    El OCR se leyo sin acentos y en minusculas para poder comparar, asi que no
    se puede copiar tal cual: «of the descendant of king ajamidha» tiene que
    entrar como «of the descendant of King Ajamīḍha». Se reaprovecha palabra por
    palabra la forma que ya tenia el repo.
    """
    forma = {}
    for w in re.findall(r"[^\s]+", glosa_vieja):
        forma.setdefault(pel(w), w)
    fuera = []
    for w in glosa_impresa.split():
        fuera.append(forma.get(pel(w), w))
    return ' '.join(fuera)


def main():
    aplicar = '--aplicar' in sys.argv
    casos = json.loads((HERE / 'difs_impreso_reales.json').read_text(encoding='utf-8'))
    hechos, saltados, dudosas, fallos = [], 0, [], []
    usados = {}
    for x in casos:
        nombre = x['file'].split('/')[-1]
        clave = x['clave'].replace('*', '')
        if truncada(x['repo'], x['impreso']):
            saltados += 1
            continue
        if (nombre, clave) in DUDOSAS:
            dudosas.append((nombre, clave, DUDOSAS[(nombre, clave)]))
            continue
        f = REPO / x['file']
        t = f.read_text(encoding='utf-8')
        viejo = f"*{clave}*—{x['repo']};"
        nuevo = f"*{clave}*—{rehacer(x['repo'], x['impreso'])};"
        n = t.count(viejo)
        if n == 0:
            fallos.append((nombre, clave, 0))
            continue
        if n > 1:
            # Clave repetida en el verso —«na» sale tres veces en sb/1/14/42—.
            # Reemplazar todas pisaria las que estan bien. Se cambia la que
            # toca: la i-esima de las que aun no se han corregido en esta
            # pasada, contando en el orden en que van en el fichero.
            visto = usados.get((x['file'], viejo), 0)
            usados[(x['file'], viejo)] = visto + 1
            trozos = t.split(viejo)
            if visto >= len(trozos) - 1:
                fallos.append((nombre, clave, n))
                continue
            t = viejo.join(trozos[:visto + 1]) + nuevo + viejo.join(trozos[visto + 1:])
        else:
            t = t.replace(viejo, nuevo)
        hechos.append((f, viejo, nuevo, nombre, clave))
        if aplicar:
            f.write_text(t, encoding='utf-8')
    for f, viejo, nuevo, nombre, clave in hechos:
        print(f"  {nombre[:22]:24} {clave[:16]:18} {viejo.split('—',1)[1][:-1][:34]!r:38} -> "
              f"{nuevo.split('—',1)[1][:-1][:34]!r}")
    print(f'\n  aplicadas: {len(hechos)}   truncadas por el OCR (saltadas): {saltados}')
    if dudosas:
        print(f'  dudosas, hace falta la imagen de la pagina: {len(dudosas)}')
        for n, k, r in dudosas:
            print(f'      {n[:22]:24} {k[:16]:18} {r}')
    if fallos:
        print(f'  sin coincidencia exacta en el .md, no tocadas: {len(fallos)}')
        for n, k, c in fallos:
            print(f'      {n[:22]:24} {k[:16]:18} aparece {c} veces')
    if not aplicar:
        print('\n  (ensayo: anade --aplicar)')
    json.dump([{'file': str(f.relative_to(REPO)), 'clave': k,
                'viejo': v.split('—', 1)[1][:-1], 'nuevo': n.split('—', 1)[1][:-1]}
               for f, v, n, _, k in hechos],
              open(HERE / 'glosas_aplicadas.json', 'w'), ensure_ascii=False, indent=1)
    return 0


if __name__ == '__main__':
    sys.exit(main())
