#!/usr/bin/env python3
"""Usa el escaneo para arbitrar las divergencias entre el repo y D1.

La idea. El diff de Surya compara repo contra ESCANEO y esta a cero abiertos:
todo lo que el repo dice distinto del impreso ya se adjudico. Asi que cuando el
repo y D1 discrepan, el escaneo desempata sin necesidad de abrir una imagen:

  el escaneo dice lo del repo  ->  el equivocado es D1
  el escaneo dice lo de D1     ->  el equivocado es el repo (raro: el diff de
                                   Surya deberia haberlo cazado; mirar el caso)
  el escaneo no dice ninguno   ->  hace falta la imagen

Como se busca. Con la palabra sola no basta —«one» sale en todas las paginas—,
asi que se toma el contexto del repo alrededor de la divergencia y se busca ese
contexto en el OCR del libro, normalizando a minusculas y sin puntuacion. Si
aparece, se mira que variante lo acompaña.

Uso: python3 arbitrar_deriva.py [--limite 30]
"""
import json
import pathlib
import re
import sys
import collections

HERE = pathlib.Path(__file__).resolve().parent
REPO = pathlib.Path('/Users/jaganat/git_projects/vedabase-original')
SURYA = HERE / 'surya'

LIBRO = {'bg': 'bhagavad-gita-as-it-is', 'sb': 'srimad-bhagavatam',
         'cc': 'sri-caitanya-caritamrta', 'kb': 'krsna-the-supreme-personality-of-godhead',
         'tlc': 'teachings-of-lord-caitanya', 'bbd': 'beyond-birth-and-death',
         'ekc': 'elevation-to-krsna-consciousness', 'tqk': 'teachings-of-queen-kunti',
         'pop': 'path-of-perfection', 'poy': 'perfection-of-yoga',
         'ssr': 'science-of-self-realization',
         # 15-ago: faltaban seis libros que SI tienen escaneo. Como el mapa se
         # consulta con .get(), pedir uno ausente no da error: devuelve cadena
         # vacia y el arbitraje queda «sin decidir» sin decir por que.
         'ttp': 'topmost-yoga-system', 'krp': 'reservoir-of-pleasure',
         'ej': 'easy-journey-to-other-planets', 'lob': 'light-of-the-bhagavata',
         'owk': 'on-the-way-to-krsna', 'pqpa': 'perfect-questions-perfect-answers',
         'rv': 'raja-vidya', 'noi': 'nectar-of-instruction',
         'nod': 'nectar-of-devotion', 'iso': 'isopanisad'}

_cache = {}


def texto_escaneo(libro):
    if libro not in _cache:
        d = SURYA / LIBRO[libro]
        t = ' '.join(f.read_text(encoding='utf-8', errors='ignore')
                     for f in sorted(d.rglob('*.surya.txt'))) if d.is_dir() else ''
        _cache[libro] = norm(t)
    return _cache[libro]


def norm(s):
    return re.sub(r'\s+', ' ', re.sub(r'[^\w\s]', ' ', (s or '').lower())).strip()


def main():
    lim = int(sys.argv[sys.argv.index('--limite') + 1]) if '--limite' in sys.argv else 30
    bloques = json.loads((HERE / 'deriva_real.json').read_text(encoding='utf-8'))
    veredicto = collections.Counter()
    salida = []
    for x in bloques:
        libro = x['ref'].split('/')[0]
        if libro not in LIBRO:
            veredicto['sin escaneo'] += 1
            continue
        t = texto_escaneo(libro)
        r, d = norm(x['repo']), norm(x['d1'])
        if not r and not d:
            veredicto['vacio'] += 1
            continue
        # con la variante sola el arbitraje es indecidible: «one» aparece en
        # todas las paginas. Se busca la variante DENTRO de su contexto —tres
        # palabras a cada lado— y solo si eso no aparece se cae a la palabra
        # suelta, que al menos distingue lo unico de lo frecuente.
        izq = ' '.join(norm(x.get('izq', '')).split()[-3:])
        der = ' '.join(norm(x.get('der', '')).split()[:3])
        con_r = ' '.join(y for y in (izq, r, der) if y)
        con_d = ' '.join(y for y in (izq, d, der) if y)
        if (izq or der) and (con_r in t or con_d in t):
            en_r, en_d = con_r in t, con_d in t
        else:
            en_r = r and r in t
            en_d = d and d in t
        if en_r and not en_d:   v = 'D1 equivocado'
        elif en_d and not en_r: v = 'repo equivocado'
        elif en_r and en_d:     v = 'los dos aparecen: hace falta imagen'
        else:                   v = 'ninguno aparece: hace falta imagen'
        veredicto[v] += 1
        salida.append({**x, 'veredicto': v})
    tot = sum(veredicto.values())
    for k, n in veredicto.most_common():
        print(f'  {n:5}  {100*n/tot:5.1f}%  {k}')
    (HERE / 'deriva_arbitrada.json').write_text(
        json.dumps(salida, ensure_ascii=False, indent=1), encoding='utf-8')
    print(f'\n  ejemplos de «repo equivocado» (los que hay que mirar):')
    for x in [y for y in salida if y['veredicto'] == 'repo equivocado'][:lim]:
        print(f"    {x['ref']:18} D1={x['d1'][:34]!r:36} repo={x['repo'][:34]!r}")
    return 0


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