#! /usr/bin/env python

###################################################
# Convert each pgfornament picture to a PDF file. #
#                                                 #
# In fact, this script creates only a Ninja       #
# build file to perform the conversion.           #
#                                                 #
# Author: Scott Pakin <scott-clsl@pakin.org>      #
###################################################

import glob
import os
import re
import subprocess
import sys
import textwrap
from pathlib import Path


def kpsewhich(fname):
    'Find a filename in the TeX tree.'
    proc = subprocess.run(['kpsewhich', fname], capture_output=True,
                          check=True, encoding='utf-8')
    return proc.stdout.strip()


def find_pgfornament_dir():
    # Find the vectorian1.pgf file then return its parent's parent directory.
    proc = subprocess.run(['kpsewhich', '--path=$TEXINPUTS', 'vectorian1.pgf'],
                          capture_output=True, encoding='utf-8')
    if proc.returncode != 0:
        return None
    fname = Path(proc.stdout.strip())
    return fname.parent.parent


def list_pgfornament_files(dname):
    '''Return a list of vectorian*.pgf numbers and a list of pgfhan*.pgf
    numbers.'''
    number_re = re.compile(r'(\d+)\.pgf')
    vectorian = set()
    for fname in (dname / "vectorian").glob('vectorian*.pgf'):
        match = number_re.search(str(fname))
        vectorian.add(int(match[1]))
    pgfhan = set()
    for fname in (dname / "pgfhan").glob('pgfhan*.pgf'):
        match = number_re.search(str(fname))
        pgfhan.add(int(match[1]))
    return sorted(vectorian), sorted(pgfhan)


def construct_phony(target, deps):
    'Return a phony build line.'
    lines = textwrap.wrap(' '.join(deps),
                          break_long_words=False, break_on_hyphens=False,
                          initial_indent='  ', subsequent_indent='  ')
    return f'build {target} : phony $\n' + ' $\n'.join(lines) + '\n'


# Generate a Ninja build file for managing PDF creation.
with open('pgfornament.ninja', 'w') as w:
    # Write a header comment.
    w.write('# This is a generated file.  DO NOT EDIT.\n')
    w.write('# Edit %s instead.\n' % os.path.abspath(sys.argv[0]))

    # Find the pgfornament base directory.  If not found, generate a
    # trivial Ninja file and exit.
    dname = find_pgfornament_dir()
    if dname is None:
        w.write('\n')
        w.write('build PGFORNAMENT : phony\n')
        sys.exit(0)

    # Determine what vectorian and pgfhan files to generate.
    vectorian, pgfhan = list_pgfornament_files(dname)

    # Write all rules.
    w.write(r'''
rule write-file
  command = /bin/echo -e '$body' > $out
  description = Creating $out

rule generate-mylatex
  command = $
    cd pgfornament ; $
    pdflatex --ini '&pdflatex' mylatex.ltx preloaded.tex
  description = Creating mylatex.fmt for faster builds

rule write-vectorian-tex
  command = $
    NUM=`echo $out | perl -ne 'm,(\d+)\.tex$$, && print "$$1\n"'` ; $
    /bin/echo -e "$
    \\\\documentclass{minimal}\\n$
    \\\\begin{document}\\n$
    \\\\newpgfornamentfamily{vectorian}\\n$
    \\\\pgfornament[height=15pt,ydelta=-5pt]{$$NUM}\\n$
    \\\\end{document}" > $out
  description = Writing $out

rule write-pgfhan-tex
  command = $
    NUM=`echo $out | perl -ne 'm,(\d+)\.tex$$, && print "$$1\n"'` ; $
    /bin/echo -e "$
    \\\\documentclass{minimal}\\n$
    \\\\begin{document}\\n$
    \\\\newpgfornamentfamily{han}\\n$
    \\\\resizebox{!}{15pt}{\\\\pgfornament[height=25pt,ydelta=-5pt]{$$NUM}}\\n$
    \\\\end{document}" > $out
  description = Writing $out

rule tex-to-pdf
  command = $
    texname="$$(basename $in)" ; $
    jname="$$(basename $in .tex)-uncrop" ; $
    cd pgfornament ; $
    pdflatex -jobname "$$jname" '&mylatex' "$$texname"
  description = pdflatex $in

rule crop-pdf
    command = pdfcrop $in $out
    description = Cropping $in to produce $out

###########################################################################
''')

    # Write build statements for creating mylatex.ltx.
    w.write(r'''
build pgfornament/preloaded.tex : write-file
  body = $
    \\documentclass{minimal}\n$
    \\usepackage{pgfornament}\n$
    \\usepackage{graphicx}\n$
    \\begin{document}\n$
    \\end{document}

build pgfornament/mylatex.fmt pgfornament/mylatex.log : generate-mylatex pgfornament/preloaded.tex | %s %s

''' % (kpsewhich('mylatex.ltx'), kpsewhich('pgfornament.sty')))

    # Write build statements for all vectorian*.tex files and all
    # pgfhan*.tex files.
    for i in vectorian:
        w.write(f'build pgfornament/vectorian{i}.tex : write-vectorian-tex\n')
    w.write('\n')
    for i in pgfhan:
        w.write(f'build pgfornament/pgfhan{i}.tex : write-pgfhan-tex\n')
    w.write('\n')

    # Write build statements to compile each LaTeX file to a PDF file.
    for i in vectorian:
        w.write(f'build pgfornament/vectorian{i}-uncrop.pdf pgfornament/vectorian{i}-uncrop.log pgfornament/vectorian{i}-uncrop.aux : tex-to-pdf pgfornament/vectorian{i}.tex | pgfornament/mylatex.fmt\n')
    w.write('\n')
    for i in pgfhan:
        w.write(f'build pgfornament/pgfhan{i}-uncrop.pdf pgfornament/pgfhan{i}-uncrop.log pgfornament/pgfhan{i}-uncrop.aux : tex-to-pdf pgfornament/pgfhan{i}.tex | pgfornament/mylatex.fmt\n')
    w.write('\n')

    # Write build statements to crop each PDF file.
    for i in vectorian:
        w.write(f'build pgfornament/vectorian{i}.pdf : crop-pdf pgfornament/vectorian{i}-uncrop.pdf\n')
    w.write('\n')
    for i in pgfhan:
        w.write(f'build pgfornament/pgfhan{i}.pdf : crop-pdf pgfornament/pgfhan{i}-uncrop.pdf\n')
    w.write('\n')

    # Write some phony build statements to aggregate all outputs.
    w.write(construct_phony('VECTORIAN',
                            [f'pgfornament/vectorian{i}.pdf'
                             for i in vectorian]))
    w.write('\n')
    w.write(construct_phony('PGFHAN',
                            [f'pgfornament/pgfhan{i}.pdf'
                             for i in pgfhan]))
    w.write('\n')
    w.write('build PGFORNAMENT : phony VECTORIAN PGFHAN\n')
