#!/usr/bin/env python3
# coding=utf8

# PREREQUISITES:
# Have a correct and up to date mappings file, updated maybe with analyze

import sys
import os
import re
import subprocess
import fontforge, psMat

# Double-quotes required here, for version-bump.sh:
# version-bump.sh is not working here, need to adjust manually!
version = "3.4.0"

dev_version = 'v2.16.0'
archive = '{}.tar.gz'.format(dev_version)

vectorsdir = 'icons'
fontdir = '.'
fontfile = 'devicons.otf'
glyphsetfile = 'i_dev.sh'
glyphsetsdir = '../../../bin/scripts/lib'

def replace_with_fixed(filename):
    base, name = os.path.split(filename)
    base, subdir = os.path.split(base)
    fixed = os.path.join(base, 'fixed', name)
    if os.path.isfile(fixed):
        print('Using fixed svg for {}'.format(name))
        return fixed
    return filename

def addIcon(codepoint, name, filename):
    """ Add one outline file and rescale/move """
    filename = os.path.join(vectorsdir, filename)
    filename = replace_with_fixed(filename)
    glyph = font.createChar(codepoint, name)
    if not os.path.isfile(filename):
        sys.exit("Mapping file refers to not existing file " + filename);
    glyph.importOutlines(filename)
    xmin, ymin, xmax, ymax = glyph.boundingBox()
    if '/vorillaz/' in filename or (xmax - xmin) < 550:
        # old and small icons are not scaled down
        pass
    else:
        glyph.transform(psMat.compose(psMat.scale(0.8, 0.8),psMat.translate(102, 102)))
    xmin, ymin, xmax, ymax = glyph.boundingBox()
    glyph.width = int(xmax + xmin) # make left and right bearings equal
    glyph.manualHints = True

def createGlyphInfo(icon_datasets, filepathname, into):
    """ Write the glyphinfo file """
    with open(filepathname, 'w', encoding = 'utf8') as f:
        f.write(u'#!/usr/bin/env bash\n')
        f.write(intro)
        f.write(u'# Script Version: (autogenerated)\n')
        f.write(u'test -n "$__i_dev_loaded" && return || __i_dev_loaded=1\n')
        for _, codepoint, _, *name in icon_datasets:
            codepoint = int(codepoint, 16)
            f.write(u"i='{}' i_dev_{}=$i\n".format(chr(codepoint), name[0]))
            for more_names in name[1:]:
                f.write(u"      i_dev_{}=$i\n".format(more_names))
        f.write(u'unset i\n')

print('\nReading mapping file')
mapping = []
with open('mapping', 'r') as f:
    for line in f.readlines():
        line = line.strip()
        if line.startswith('#') or len(line) < 1:
            continue
        mapping.append(tuple(re.split(' +', line.strip())))
print('Found {} entries'.format(len(mapping)))
mapping.sort(key=(lambda x: x[1]))

if not os.path.isfile(archive):
    print('Fetching Devicons archive "{}"\n'.format(archive))
    if subprocess.call('curl -OL https://github.com/devicons/devicon/archive/refs/tags/' + archive, shell=True):
        sys.exit('Error fetching Devicons archive')

print('\nUnpacking Devicons archive')
if subprocess.call('rm -rf devicon-* icons && tar zxf ' + archive + \
        ' && mv devicon-*/icons .', shell=True):
    sys.exit('Error unpacking archive')

print('\nMixing Vorillaz Devicons and possible fixes in')
if subprocess.call('cp -r vorillaz fixed icons', shell=True):
    sys.exit('Error mixing ...')


svg_dirs = os.listdir(vectorsdir)
svgs = []
for d in svg_dirs:
    svgs += os.listdir(os.path.join(vectorsdir, d))
print('Found {} svgs'.format(len(svgs)))

font = fontforge.font()
font.fontname = 'Devicons-NerdFont-Regular'
font.fullname = 'Devicons Nerd Font Regular'
font.familyname = 'Devicons Nerd Font'
font.ascent = 960
font.descent = 64
font.em = 1024
font.encoding = 'UnicodeFull'

# Add valid space glyph to avoid "unknown character" box on IE11
glyph = font.createChar(32)
glyph.width = 512

font.sfntRevision = None # Auto-set (refreshed) by fontforge
font.version = version
font.copyright = 'Devicons devs'
font.appendSFNTName('English (US)', 'Version', archive + '; ' + version)
font.appendSFNTName('English (US)', 'Vendor URL', 'https://github.com/ryanoasis/nerd-fonts')
font.appendSFNTName('English (US)', 'Copyright', 'See https://github.com/devicons/devicon')

for codepoint, _, file, *names in mapping:
    codepoint = int(codepoint, 16)
    addIcon(codepoint, names[0], file)

num_icons = len(mapping)

print('Generating {} with {} glyphs'.format(fontfile, num_icons))
font.generate(os.path.join(fontdir, fontfile), flags=("no-FFTM-table",))

codepoints = [ int(p, 16) for _, p, *_ in mapping ]
aliases = [ len(n) - 1 for _, _, _, *n in mapping ]
min_code = min(codepoints)
max_code = max(codepoints)
has_gaps = max_code - min_code + 1 != len(codepoints)
intro  = u'# Devicons (version {}, {} icons, {} aliases)\n'.format(dev_version, num_icons, sum(aliases))
intro += u'# Does not include all icons of the release\n'
intro += u'# Codepoints: {:X}-{:X}{}\n'.format(min_code, max_code, ' with gaps' if has_gaps else '')
intro += u'# Nerd Fonts Version: {}\n'.format(version)

print('Generating GlyphInfo {}'.format(glyphsetfile))
createGlyphInfo(mapping, os.path.join(glyphsetsdir, glyphsetfile), intro)
print('Finished')
