#!/usr/bin/env python3
"""Encuentra la pagina del escaneo donde esta un pasaje y la saca a PNG.

Para adjudicar una divergencia hace falta la pagina, y `deriva_arbitrada.json`
no la guarda: solo trae la referencia y el contexto. Esto busca el contexto en
el OCR pagina a pagina, y con la que casa llama a `pagina_png.py`.

Se busca por el contexto y no por la palabra suelta: «one» sale en todas las
paginas del libro y no serviria de nada.

Uso:
    python3 pagina_de_ref.py cc/adi/5/18 "Śrīla Bhaktivinoda Ṭhākura" /tmp/x.png
"""
import pathlib
import re
import subprocess
import sys

HERE = pathlib.Path(__file__).resolve().parent
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', 'nod': 'nectar-of-devotion',
         'lob': 'light-of-the-bhagavata', 'iso': 'isopanisad', 'noi': 'nectar-of-instruction'}


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


_CACHE_PAG = {}


def _paginas(d):
    """[(fichero, texto normalizado)] de un libro, cacheado.

    Sin cache, cada llamada relee las ~5.000 paginas del Bhagavatam; con una
    barrida de cientos de ocurrencias eso son horas."""
    k = str(d)
    if k not in _CACHE_PAG:
        _CACHE_PAG[k] = [(f, norm(f.read_text(encoding='utf-8', errors='ignore')))
                         for f in sorted(d.rglob('*.surya.txt'))]
    return _CACHE_PAG[k]


def localizar(ref, frase):
    """(stem, numero_de_pagina) de la pagina que contiene `frase`.

    Se prueba la frase entera y, si no aparece, ventanas cada vez mas cortas.
    El contexto viene del repo normalizado y el OCR no lo reproduce palabra por
    palabra —una errata, un guion de fin de linea, una cursiva mal leida— asi
    que exigir la frase completa fallaba en la mayoria de los casos. Con
    ventanas de seis palabras deslizantes casi siempre hay un tramo que casa, y
    seis palabras seguidas ya no salen dos veces en un libro por casualidad.
    """
    d = SURYA / LIBRO.get(ref.split('/')[0], '')
    if not d.is_dir():
        return None
    pal = norm(frase).split()
    if len(pal) < 4:
        return None
    intentos = [' '.join(pal)]
    for ancho in (10, 8, 6, 5, 4):
        if len(pal) < ancho:
            continue
        intentos += [' '.join(pal[i:i + ancho]) for i in range(len(pal) - ancho + 1)]
    paginas = _paginas(d)
    for aguja in intentos:
        if len(aguja) < 14:
            continue
        hit = [f for f, t in paginas if aguja in t]
        if len(hit) == 1:
            f = hit[0]
            return f.parent.name, int(f.stem.replace('.surya', '').lstrip('p'))
    return None


def main():
    ref, frase = sys.argv[1], sys.argv[2]
    salida = sys.argv[3] if len(sys.argv) > 3 else '/tmp/pagina.png'
    hit = localizar(ref, frase)
    if not hit:
        print(f'  no encuentro la pagina de {ref} con {frase[:40]!r}')
        return 1
    stem, pag = hit
    print(f'  {ref}: {stem} p.{pag}')
    subprocess.run([sys.executable, str(HERE / 'pagina_png.py'), stem, str(pag), salida],
                   check=False)
    return 0


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