#!/usr/bin/env python3
"""junta-dias: deja al lado de cada circuito el .dia de Simusol del que salio.

    junta-dias                     el corpus de siru (siru/siru/corpus/corpus)
    junta-dias DIR...              otros directorios
    junta-dias --prueba            solo dice que copiaria

Los .d que hizo Simusol dicen de que diagrama salieron ("a partir del
archivo-diagrama ../cprojects/tanque.dia"). Para cada .d y .ds se busca ese
.dia junto al circuito y, si no esta, uno con ese nombre en el arbol de siru
(no en los viejos: siruviejo, viejos, ds2viejos); de varios, el que mas
ramas comparte con el circuito. Se copia con svn copy (conserva la historia
y el original queda donde estaba) como NOMBRE.dia, junto a NOMBRE.d o
NOMBRE.ds. Se copia aunque el diagrama tenga menos ramas que el circuito
(un .ds armado a mano a partir de otro): dibuja hace las que faltan con el
conjunto de formas que predomina. Despues, dia2formas NOMBRE.dia.

Copyright (C) Diego Saravia <dsa@unsa.edu.ar>
GPL version 3 o posterior.
"""
import argparse
import importlib.machinery
import importlib.util
import os
import re
import shutil
import subprocess
import sys

AQUI = os.path.dirname(os.path.realpath(__file__))
SIRU = os.path.normpath(os.path.join(AQUI, ".."))
CORPUS = os.path.join(SIRU, "siru", "corpus", "corpus")
VIEJOS = ("siruviejo", "viejos", "ds2viejos", "viejo")


def _dia2formas():
    cargador = importlib.machinery.SourceFileLoader("dia2formas", os.path.join(AQUI, "dia2formas"))
    spec = importlib.util.spec_from_loader("dia2formas", cargador)
    m = importlib.util.module_from_spec(spec)
    cargador.exec_module(m)
    return m


D2F = _dia2formas()
_indice = None


def indice_dia():
    """nombre de archivo .dia -> rutas, en todo el arbol de siru salvo los viejos"""
    global _indice
    if _indice is None:
        _indice = {}
        for raiz, dirs, archivos in os.walk(SIRU):
            dirs[:] = [d for d in dirs if d not in (".svn", "node_modules") + VIEJOS]
            for a in archivos:
                if a.endswith(".dia"):
                    _indice.setdefault(a, []).append(os.path.join(raiz, a))
    return _indice


def busca_dia(circuito, ramas):
    nombrado = None
    for l in open(circuito, encoding="utf-8", errors="replace"):
        m = re.search(r"archivo-diagrama\s+(\S+\.dia)", l)
        if m:
            nombrado = m.group(1)
            break
    if not nombrado:
        return None
    junto = os.path.normpath(os.path.join(os.path.dirname(circuito), nombrado))
    candidatos = [junto] if os.path.exists(junto) else indice_dia().get(os.path.basename(nombrado), [])
    mejor, cuantas = None, -1
    for c in candidatos:
        try:
            n = len({x[0] for x in D2F.nombres_de(D2F.lee_dia(c), ramas)} & ramas)
        except OSError:
            continue
        if n > cuantas:
            mejor, cuantas = c, n
    return mejor


def main():
    a = argparse.ArgumentParser(description="Copia junto a cada circuito el .dia de Simusol del que salio (NOMBRE.dia).")
    a.add_argument("dirs", nargs="*", default=[CORPUS])
    a.add_argument("--prueba", action="store_true", help="solo decir que copiaria")
    o = a.parse_args()
    copias, ya, sin = 0, 0, 0
    for d in o.dirs:
        for raiz, dirs, archivos in os.walk(d):
            dirs[:] = sorted(x for x in dirs if x != ".svn")
            for f in sorted(archivos):
                if not f.endswith((".d", ".ds")):
                    continue
                c = os.path.join(raiz, f)
                destino = os.path.splitext(c)[0] + ".dia"
                if os.path.exists(destino):
                    ya += 1
                    continue
                ramas = D2F.ramas_del_circuito(c)
                dia = busca_dia(c, ramas) if ramas else None
                if not dia:
                    sin += 1
                    continue
                comunes = len({x[0] for x in D2F.nombres_de(D2F.lee_dia(dia), ramas)} & ramas)
                print("%s <- %s (%d de %d ramas)" % (os.path.relpath(destino), os.path.relpath(dia), comunes, len(ramas)))
                if not o.prueba:
                    r = subprocess.run(["svn", "copy", "-q", dia, destino], capture_output=True, text=True)
                    if r.returncode:            # el original no esta versionado: copia simple
                        shutil.copy2(dia, destino)
                        subprocess.run(["svn", "add", "-q", destino])
                copias += 1
    print("%d copiados, %d ya tenian su .dia, %d sin .dia" % (copias, ya, sin))


if __name__ == "__main__":
    main()
