#!/usr/bin/env python3
"""dibuja-corpus: dibuja cada circuito de un corpus al lado de su fuente.

    dibuja-corpus                     el corpus de siru (siru/siru/corpus/corpus)
    dibuja-corpus DIR...              otros directorios
    dibuja-corpus --todos             rehace tambien los que ya estan al dia
    dibuja-corpus --formas            antes, dia2formas: NOMBRE.formas de cada
                                      circuito cuyo .dia de Simusol se encuentra

Por cada .d y .ds (no los .ds2) escribe NOMBRE.d.svg o NOMBRE.ds.svg en el
mismo directorio (con la extension, porque hay circuitos con .d y .ds). Solo
rehace los que no tienen dibujo o cuya fuente es mas nueva. Al final dice
cuantos dibujo, cuantos no son circuitos (sistemas de ecuaciones sin ramas)
y cuales rechazo d2datdinc, con el motivo.

Copyright (C) Diego Saravia <dsa@unsa.edu.ar>
GPL version 3 o posterior.
"""
import argparse
import os
import subprocess
import sys
from concurrent.futures import ThreadPoolExecutor

AQUI = os.path.dirname(os.path.realpath(__file__))
DIBUJA = os.path.join(AQUI, "dibuja")
CORPUS = os.path.normpath(os.path.join(AQUI, "..", "siru", "corpus", "corpus"))


def fuentes(dirs):
    for d in dirs:
        for raiz, subdirs, archivos in os.walk(d):
            subdirs[:] = sorted(s for s in subdirs if s != ".svn")
            for a in sorted(archivos):
                if a.endswith(".d") or a.endswith(".ds"):
                    yield os.path.join(raiz, a)


def dibuja(fuente, todos):
    svg = fuente + ".svg"
    if not todos and os.path.exists(svg) and os.path.getmtime(svg) >= os.path.getmtime(fuente):
        return "al dia", fuente, ""
    # d2datdinc busca los includes junto al circuito: se corre en su directorio
    r = subprocess.run([DIBUJA, os.path.basename(fuente), "-o", os.path.basename(svg)],
                       cwd=os.path.dirname(fuente), capture_output=True, text=True)
    if r.returncode == 0:
        return "dibujado", fuente, ""
    motivo = (r.stderr.strip().splitlines() or ["?"])[-1]
    if "no tiene ramas" in motivo:
        return "sin ramas", fuente, ""
    return "rechazado", fuente, motivo


def main():
    a = argparse.ArgumentParser(description="Dibuja cada .d y .ds de un corpus al lado de su fuente (NOMBRE.d.svg).")
    a.add_argument("dirs", nargs="*", default=[CORPUS])
    a.add_argument("--todos", action="store_true", help="rehacer tambien los que estan al dia")
    a.add_argument("-j", type=int, default=os.cpu_count() or 4, help="cuantos a la vez")
    a.add_argument("--formas", action="store_true",
                   help="antes de dibujar, dia2formas -r: las formas de Dia de cada circuito con su .dia")
    o = a.parse_args()
    if o.formas:
        subprocess.run([os.path.join(AQUI, "dia2formas"), "-r"] + o.dirs, check=False)
    lista = list(fuentes(o.dirs))
    cuenta = {}
    rechazados = []
    with ThreadPoolExecutor(o.j) as ex:
        for estado, fuente, motivo in ex.map(lambda f: dibuja(f, o.todos), lista):
            cuenta[estado] = cuenta.get(estado, 0) + 1
            if estado == "rechazado":
                rechazados.append((fuente, motivo))
    for fuente, motivo in rechazados:
        print("rechazado: %s: %s" % (os.path.relpath(fuente), motivo[:160]))
    print("%d circuitos: %s" % (len(lista), ", ".join("%d %s" % (n, e) for e, n in sorted(cuenta.items()))))
    return 0


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