#! /usr/bin/env python

###############################################
# Convert each utfsym picture to a PDF file.  #
#                                             #
# In fact, this script creates only a Ninja   #
# build file to perform the conversion and a  #
# fakeutfsym.sty file that uses the generated #
# PDF files.                                  #
#                                             #
# Author: Scott Pakin <scott-clsl@pakin.org>  #
###############################################

import glob
import os
import re
import subprocess
import sys
import textwrap


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


# If utfsym.sty doesn't exist, write a dummy utfsym.ninja and exit.
sty = kpsewhich('utfsym.sty', must_exist=False)
if sty is None:
    with open('utfsym.ninja', 'w') as w:
        # Write some boilerplate code.
        w.write('# This is a generated file.  DO NOT EDIT.\n')
        w.write('# Edit %s instead.\n' % os.path.abspath(sys.argv[0]))
        w.write('''
rule touch
  command = touch $out

build fakeutfsym.sty : touch

build UTFSYM : phony fakeutfsym.sty
''')
    sys.exit(0)


# Extract the package description from utfsym.sty.
desc_re = re.compile(r'\\ProvidesExplPackage\{utfsym\}(\{.*\})$')
with open(sty) as r:
    for ln in r:
        match = desc_re.search(ln)
        if match is not None:
            desc = match[1]
            break

# Acquire a list of all defined symbols in the form "usym<code_point>".
udir = os.path.dirname(kpsewhich('usym1F600.tikz'))
tikz_files = glob.glob(os.path.join(udir, '*.tikz'))
symbols = [os.path.splitext(os.path.basename(fn))[0] for fn in tikz_files]
symbols.sort(key=lambda s: int(s[4:], 16))

# Generate a Ninja build file for managing PDF creation.
with open('utfsym.ninja', 'w') as w:
    # Write some boilerplate code.
    w.write('# This is a generated file.  DO NOT EDIT.\n')
    w.write('# Edit %s instead.\n' % os.path.abspath(sys.argv[0]))
    w.write(r'''
rule write-file
  command = /bin/echo -e '$body' > $out
  description = Creating $out

build utfsym/preloaded.tex : write-file
  body = $
    \\documentclass{minimal}\n$
    \\usepackage{utfsym}\n$
    \\begin{document}\n$
    \\end{document}

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

''')
    w.write('build utfsym/mylatex.fmt utfsym/mylatex.log :'
            ' generate-mylatex utfsym/preloaded.tex | %s %s\n' %
            (kpsewhich('mylatex.ltx'), kpsewhich('utfsym.sty')))
    w.write(r'''
rule write-symbol-tex
  command = bash -c '$
    base=$$(basename $out .tex) ; $
    sym=$${base:4} ; $
    echo -e "$
    \\\\documentclass{minimal}\\n$
    \\\\begin{document}\\n$
    \\\\usym{$$sym}\\n$
    \\\\end{document}" > $out'
      description = Writing $out

''')

    # For each symbol defined by utfsym.sty, create a LaTeX file.
    for base in symbols:
        w.write(f'build utfsym/{base}.tex : write-symbol-tex\n')

    # Compile each LaTeX file to a PDF file.
    w.write(r'''
rule tex-to-pdf
  command = $
    texname="$$(basename $in)" ; $
    jname="$$(basename $in .tex)-uncrop" ; $
    cd utfsym ; $
    pdflatex -jobname "$$jname" '&mylatex' "$$texname"
  description = pdflatex $in

''')
    for base in symbols:
        w.write(f'build utfsym/{base}-uncrop.pdf utfsym/{base}-uncrop.log utfsym/{base}-uncrop.aux : tex-to-pdf utfsym/{base}.tex | utfsym/mylatex.fmt\n')
    w.write('\n')

    # Crop each PDF file.
    w.write('rule crop-pdf\n')
    w.write('  command = pdfcrop $in $out\n')
    w.write('  description = Cropping $in to produce $out\n\n')
    for sym in symbols:
        w.write(f'build utfsym/{sym}.pdf : crop-pdf utfsym/{sym}-uncrop.pdf\n')

    # Create a fakeutfsym.sty file.
    w.write(r'''
build fakeutfsym.sty : write-file
  body = $
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n$
    % This is a generated file.  DO NOT EDIT. %\n$
    % Edit makefakeutfsym instead.            %\n$
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n$
    \n$''')
    w.write(r'''
    \\NeedsTeXFormat{LaTeX2e}\n$
    \\ProvidesExplPackage{fakeutfsym}%s\n$
    \\RequirePackage{graphicx}\n$
    \n$
    \\NewDocumentCommand{\\usym}{m}{\\includegraphics{utfsym/usym#1}}\n$
    \\NewDocumentCommand{\\usymW}{m m}{\\includegraphics[width=#2]{utfsym/usym#1}}\n$
    \\NewDocumentCommand{\\usymH}{m m}{\\includegraphics[height=#2]{utfsym/usym#1}}\n$
    \n$
    \\endinput
''' % desc)
    w.write('\n')

    # Create a phony symbol that depends on fakeutfsym.sty and all
    # generated PDF files.
    w.write('build UTFSYM : phony $\n')
    phony = [f'utfsym/{sym}.pdf' for sym in symbols] + ['fakeutfsym.sty']
    lines = textwrap.wrap(' '.join(phony),
                          break_long_words=False, break_on_hyphens=False,
                          initial_indent='  ', subsequent_indent='  ')
    w.write('%s\n' % ' $\n'.join(lines))
