#! /usr/bin/env python

#################################################
# Convert each lilyglyphs symbol 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


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 header_string():
    'Return a "generated file" header string.'
    full_name = os.path.abspath(sys.argv[0])
    gen_line = 'This is a generated file.  DO NOT EDIT.'
    edit_line = f'Edit {full_name} instead.'
    max_chars = max(len(gen_line), len(edit_line))
    hash_line = '#' * (max_chars + 4)
    return '\n'.join([
        hash_line,
        '# %-*.*s #' % (max_chars, max_chars, gen_line),
        '# %-*.*s #' % (max_chars, max_chars, edit_line),
        hash_line,
        '',
    ])


def symbol_names(fname):
    'Extract all symbol names from a given font file.'
    proc = subprocess.run(['otfinfo', '--glyphs', fname],
                          capture_output=True, check=True, encoding='utf-8')
    return [sym
            for sym in proc.stdout.split()
            if sym != '.notdef']


def find_logo_file():
    'Return the absolute path to lilyglyphs_logo.pdf.'
    proc = subprocess.run([
        'texdoc',
        '--list',
        '--nointeract',
        'lilyglyphs_logo.pdf',
    ],
                          capture_output=True, check=True, encoding='utf-8')
    return proc.stdout.split()[1]


# If we don't have emmentaler-16.otf, generate a do-nothing Ninja file
# and exit.
font_path = kpsewhich('emmentaler-16.otf')
if font_path == '':
    with open('lilyglyphs.ninja', 'w') as w:
        w.write(header_string())
    sys.exit(0)

# Generate a Ninja file that builds a PDF file for each lilyglyphs character.
with open('lilyglyphs.ninja', 'w') as w:
    w.write(header_string())
    w.write('''
rule write-file
  command = /bin/echo -e '$body' > $out
  description = Creating $out

# Generate a FontForge script that extracts all symbols from a font
# into named, (rather than numbered) EPS files.
build extract-by-name.pe : write-file
  body = $
    Open($$1)\\n$
    Select(0x0000, 0xFFFF)\\n$
    Export("%n.eps")

rule extract-lilyglyphs-symbols
  command = cd lilyglyphs ; fontforge -script ../$in $font
  description = Generating an EPS file for each Lilyglyphs character

''')

    # Extract all EPS files at once.
    sym_list = symbol_names(font_path)
    w.write('# Extract all symbols as EPS files at once.\n')
    w.write('build %s : extract-lilyglyphs-symbols extract-by-name.pe\n' %
            ' '.join(['lilyglyphs/%s.eps' % sym[:40] for sym in sym_list]))
    w.write(f'  font = {font_path}\n')

    # Convert each EPS file to a PDF file.
    w.write('''
rule eps-to-pdf
  command = epstopdf $in $out
  description = Converting $in to $out

''')
    w.write('# Convert each EPS file to a PDF file.\n')
    for sym in sym_list:
        if sym == 'space':
            continue
        sym_trunc = sym[:40]  # FontForge truncates names to 40 characters.
        w.write(f'build lilyglyphs/{sym}.pdf : eps-to-pdf lilyglyphs/{sym_trunc}.eps\n')

    # Copy the lilyglyphs logo file locally and crop it.
    logo_path = find_logo_file()
    w.write('''
rule copy-and-crop
  command = $
    cp $in $UNCROP ; $
    pdfcrop $UNCROP $out
  description = Copying $in to $out and cropping it

# Copy lilyglyphs_logo.pdf to the lilyglyphs directory and crop it.
build lilyglyphs/lilyglyphs_logo.pdf : copy-and-crop %s
  UNCROP = lilyglyphs/lilyglyphs_logo_uncrop.pdf
''' % logo_path)

    # Create a phony rule that depends on all generated PDF files.
    w.write('# Make LILYGLYPHS depend on all generated files.\n')
    w.write('build LILYGLYPHS : phony')
    for sym in sym_list + ['lilyglyphs_logo']:
        if sym != 'space':
            w.write(f' $\n  lilyglyphs/{sym}.pdf')
    w.write('\n')
