#!/usr/bin/env python
from fontTools.ttLib import TTFont
import os, sys, re

# Adoptation of fonttools/blob/master/Snippets/rename-fonts.py

WINDOWS_ENGLISH_IDS = 3, 1, 0x409
MAC_ROMAN_IDS = 1, 0, 0

LEGACY_FAMILY      = 1
TRUETYPE_UNIQUE_ID = 3
FULL_NAME          = 4
POSTSCRIPT_NAME    = 6
PREFERRED_FAMILY   = 16
SUBFAMILY_NAME     = 17
WWS_FAMILY         = 21


FAMILY_RELATED_IDS = set([
  LEGACY_FAMILY,
  TRUETYPE_UNIQUE_ID,
  FULL_NAME,
  POSTSCRIPT_NAME,
  PREFERRED_FAMILY,
  WWS_FAMILY,
])

whitespace_re = re.compile(r'\s+')


def removeWhitespace(s):
  return whitespace_re.sub("", s)


def setFullName(font, fullName):
  nameTable = font["name"]
  nameTable.setName(fullName, FULL_NAME, 1, 0, 0)     # mac
  nameTable.setName(fullName, FULL_NAME, 3, 1, 0x409) # windows


def getFamilyName(font):
  nameTable = font["name"]
  r = None
  for plat_id, enc_id, lang_id in (WINDOWS_ENGLISH_IDS, MAC_ROMAN_IDS):
    for name_id in (PREFERRED_FAMILY, LEGACY_FAMILY):
      r = nameTable.getName(nameID=name_id, platformID=plat_id, platEncID=enc_id, langID=lang_id)
      if r is not None:
        break
    if r is not None:
      break
  if not r:
    raise ValueError("family name not found")
  return r.toUnicode()


def removeWhitespaceFromStyles(font):
  familyName = getFamilyName(font)

  # collect subfamily (style) name IDs for variable font's named instances
  vfInstanceSubfamilyNameIds = set()
  if "fvar" in font:
    for namedInstance in font["fvar"].instances:
      vfInstanceSubfamilyNameIds.add(namedInstance.subfamilyNameID)

  nameTable = font["name"]
  for rec in nameTable.names:
    rid = rec.nameID
    if rid in (FULL_NAME, LEGACY_FAMILY):
      # style part of family name
      s = rec.toUnicode()
      start = s.find(familyName)
      if start != -1:
        s = familyName + " " + removeWhitespace(s[start + len(familyName):])
      else:
        s = removeWhitespace(s)
      rec.string = s
    if rid in (SUBFAMILY_NAME,) or rid in vfInstanceSubfamilyNameIds:
      rec.string = removeWhitespace(rec.toUnicode())
    # else: ignore standard names unrelated to style


def setFamilyName(font, nextFamilyName):
  prevFamilyName = getFamilyName(font)
  if prevFamilyName == nextFamilyName:
    return
    # raise Exception("identical family name")

  def renameRecord(nameRecord, prevFamilyName, nextFamilyName):
    # replaces prevFamilyName with nextFamilyName in nameRecord
    s = nameRecord.toUnicode()
    start = s.find(prevFamilyName)
    if start != -1:
      end = start + len(prevFamilyName)
      nextFamilyName = s[:start] + nextFamilyName + s[end:]
    nameRecord.string = nextFamilyName
    return s, nextFamilyName

  # postcript name can't contain spaces
  psPrevFamilyName = prevFamilyName.replace(" ", "")
  psNextFamilyName = nextFamilyName.replace(" ", "")
  for rec in font["name"].names:
    name_id = rec.nameID
    if name_id not in FAMILY_RELATED_IDS:
      # leave uninteresting records unmodified
      continue
    if name_id == POSTSCRIPT_NAME:
      old, new = renameRecord(rec, psPrevFamilyName, psNextFamilyName)
    elif name_id == TRUETYPE_UNIQUE_ID:
      # The Truetype Unique ID rec may contain either the PostScript Name or the Full Name
      if psPrevFamilyName in rec.toUnicode():
        # Note: This is flawed -- a font called "Foo" renamed to "Bar Lol";
        # if this record is not a PS record, it will incorrectly be rename "BarLol".
        # However, in practice this is not abig deal since it's just an ID.
        old, new = renameRecord(rec, psPrevFamilyName, psNextFamilyName)
      else:
        old, new = renameRecord(rec, prevFamilyName, nextFamilyName)
    else:
      old, new = renameRecord(rec, prevFamilyName, nextFamilyName)
    # print("  %r: '%s' -> '%s'" % (rec, old, new))



def loadFont(file):
  return TTFont(file, recalcBBoxes=False, recalcTimestamp=False)


def renameFontFamily(infile, outfile, newFamilyName):
  font = loadFont(infile)
  setFamilyName(font, newFamilyName)
  # print('write "%s"' % outfile)
  font.save(outfile)
  font.close()



def main():
  infile = "./build/fonts/var/Inter.var.ttf"
  outfile = "./build/tmp/var2.otf"
  renameFontFamily(infile, outfile, "Inter V")
  print("%s familyName: %r" % (infile, getFamilyName(loadFont(infile)) ))
  print("%s familyName: %r" % (outfile, getFamilyName(loadFont(outfile)) ))

if __name__ == "__main__":
  sys.exit(main())

# Similar to:
# ttx -i -e -o ./build/tmp/var.ttx ./build/fonts/var/Inter.var.ttf
# ttx -b --no-recalc-timestamp -o ./build/tmp/var.ttf ./build/tmp/var.ttx
