"""
Instantiate a variation font.  Run, eg:

$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85
"""
from fontTools.misc.fixedTools import floatToFixedToFloat, otRound, floatToFixed
from fontTools.pens.boundsPen import BoundsPen
from fontTools.ttLib import TTFont, newTable
from fontTools.ttLib.tables import ttProgram
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates, flagOverlapSimple, OVERLAP_COMPOUND
from fontTools.varLib.models import (
	supportScalar,
	normalizeLocation,
	piecewiseLinearMap,
)
from fontTools.varLib.merger import MutatorMerger
from fontTools.varLib.varStore import VarStoreInstancer
from fontTools.varLib.mvar import MVAR_ENTRIES
from fontTools.varLib.iup import iup_delta
import fontTools.subset.cff
import os.path
import logging
from io import BytesIO


log = logging.getLogger("fontTools.varlib.mutator")

# map 'wdth' axis (1..200) to OS/2.usWidthClass (1..9), rounding to closest
OS2_WIDTH_CLASS_VALUES = {}
percents = [50.0, 62.5, 75.0, 87.5, 100.0, 112.5, 125.0, 150.0, 200.0]
for i, (prev, curr) in enumerate(zip(percents[:-1], percents[1:]), start=1):
	half = (prev + curr) / 2
	OS2_WIDTH_CLASS_VALUES[half] = i


def interpolate_cff2_PrivateDict(topDict, interpolateFromDeltas):
	pd_blend_lists = ("BlueValues", "OtherBlues", "FamilyBlues",
						"FamilyOtherBlues", "StemSnapH",
						"StemSnapV")
	pd_blend_values = ("BlueScale", "BlueShift",
						"BlueFuzz", "StdHW", "StdVW")
	for fontDict in topDict.FDArray:
		pd = fontDict.Private
		vsindex = pd.vsindex if (hasattr(pd, 'vsindex')) else 0
		for key, value in pd.rawDict.items():
			if (key in pd_blend_values) and isinstance(value, list):
					delta = interpolateFromDeltas(vsindex, value[1:])
					pd.rawDict[key] = otRound(value[0] + delta)
			elif (key in pd_blend_lists) and isinstance(value[0], list):
				"""If any argument in a BlueValues list is a blend list,
				then they all are. The first value of each list is an
				absolute value. The delta tuples are calculated from
				relative master values, hence we need to append all the
				deltas to date to each successive absolute value."""
				delta = 0
				for i, val_list in enumerate(value):
					delta += otRound(interpolateFromDeltas(vsindex,
										val_list[1:]))
					value[i] = val_list[0] + delta


def interpolate_cff2_charstrings(topDict, interpolateFromDeltas, glyphOrder):
	charstrings = topDict.CharStrings
	for gname in glyphOrder:
		# Interpolate charstring
		# e.g replace blend op args with regular args,
		# and use and discard vsindex op.
		charstring = charstrings[gname]
		new_program = []
		vsindex = 0
		last_i = 0
		for i, token in enumerate(charstring.program):
			if token == 'vsindex':
				vsindex = charstring.program[i - 1]
				if last_i != 0:
					new_program.extend(charstring.program[last_i:i - 1])
				last_i = i + 1
			elif token == 'blend':
				num_regions = charstring.getNumRegions(vsindex)
				numMasters = 1 + num_regions
				num_args = charstring.program[i - 1]
				# The program list starting at program[i] is now:
				# ..args for following operations
				# num_args values  from the default font
				# num_args tuples, each with numMasters-1 delta values
				# num_blend_args
				# 'blend'
				argi = i - (num_args * numMasters + 1)
				end_args = tuplei = argi + num_args
				while argi < end_args:
					next_ti = tuplei + num_regions
					deltas = charstring.program[tuplei:next_ti]
					delta = interpolateFromDeltas(vsindex, deltas)
					charstring.program[argi] += otRound(delta)
					tuplei = next_ti
					argi += 1
				new_program.extend(charstring.program[last_i:end_args])
				last_i = i + 1
		if last_i != 0:
			new_program.extend(charstring.program[last_i:])
			charstring.program = new_program


def interpolate_cff2_metrics(varfont, topDict, glyphOrder, loc):
	"""Unlike TrueType glyphs, neither advance width nor bounding box
	info is stored in a CFF2 charstring. The width data exists only in
	the hmtx and HVAR tables. Since LSB data cannot be interpolated
	reliably from the master LSB values in the hmtx table, we traverse
	the charstring to determine the actual bound box. """

	charstrings = topDict.CharStrings
	boundsPen = BoundsPen(glyphOrder)
	hmtx = varfont['hmtx']
	hvar_table = None
	if 'HVAR' in varfont:
		hvar_table = varfont['HVAR'].table
		fvar = varfont['fvar']
		varStoreInstancer = VarStoreInstancer(hvar_table.VarStore, fvar.axes, loc)

	for gid, gname in enumerate(glyphOrder):
		entry = list(hmtx[gname])
		# get width delta.
		if hvar_table:
			if hvar_table.AdvWidthMap:
				width_idx = hvar_table.AdvWidthMap.mapping[gname]
			else:
				width_idx = gid
			width_delta = otRound(varStoreInstancer[width_idx])
		else:
			width_delta = 0

		# get LSB.
		boundsPen.init()
		charstring = charstrings[gname]
		charstring.draw(boundsPen)
		if boundsPen.bounds is None:
			# Happens with non-marking glyphs
			lsb_delta = 0
		else:
			lsb = boundsPen.bounds[0]
		lsb_delta = entry[1] - lsb

		if lsb_delta or width_delta:
			if width_delta:
				entry[0] += width_delta
			if lsb_delta:
				entry[1] = lsb
			hmtx[gname] = tuple(entry)


def instantiateVariableFont(varfont, location, inplace=False, overlap=True):
	""" Generate a static instance from a variable TTFont and a dictionary
	defining the desired location along the variable font's axes.
	The location values must be specified as user-space coordinates, e.g.:

		{'wght': 400, 'wdth': 100}

	By default, a new TTFont object is returned. If ``inplace`` is True, the
	input varfont is modified and reduced to a static font.

	When the overlap parameter is defined as True,
	OVERLAP_SIMPLE and OVERLAP_COMPOUND bits are set to 1.  See
	https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
	"""
	if not inplace:
		# make a copy to leave input varfont unmodified
		stream = BytesIO()
		varfont.save(stream)
		stream.seek(0)
		varfont = TTFont(stream)

	fvar = varfont['fvar']
	axes = {a.axisTag:(a.minValue,a.defaultValue,a.maxValue) for a in fvar.axes}
	loc = normalizeLocation(location, axes)
	if 'avar' in varfont:
		maps = varfont['avar'].segments
		loc = {k: piecewiseLinearMap(v, maps[k]) for k,v in loc.items()}
	# Quantize to F2Dot14, to avoid surprise interpolations.
	loc = {k:floatToFixedToFloat(v, 14) for k,v in loc.items()}
	# Location is normalized now
	log.info("Normalized location: %s", loc)

	if 'gvar' in varfont:
		log.info("Mutating glyf/gvar tables")
		gvar = varfont['gvar']
		glyf = varfont['glyf']
		# get list of glyph names in gvar sorted by component depth
		glyphnames = sorted(
			gvar.variations.keys(),
			key=lambda name: (
				glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth
				if glyf[name].isComposite() else 0,
				name))
		for glyphname in glyphnames:
			variations = gvar.variations[glyphname]
			coordinates, _ = glyf.getCoordinatesAndControls(glyphname, varfont)
			origCoords, endPts = None, None
			for var in variations:
				scalar = supportScalar(loc, var.axes)
				if not scalar: continue
				delta = var.coordinates
				if None in delta:
					if origCoords is None:
						origCoords, g = glyf.getCoordinatesAndControls(glyphname, varfont)
					delta = iup_delta(delta, origCoords, g.endPts)
				coordinates += GlyphCoordinates(delta) * scalar
			glyf.setCoordinates(glyphname, coordinates, varfont)
	else:
		glyf = None

	if 'cvar' in varfont:
		log.info("Mutating cvt/cvar tables")
		cvar = varfont['cvar']
		cvt = varfont['cvt ']
		deltas = {}
		for var in cvar.variations:
			scalar = supportScalar(loc, var.axes)
			if not scalar: continue
			for i, c in enumerate(var.coordinates):
				if c is not None:
					deltas[i] = deltas.get(i, 0) + scalar * c
		for i, delta in deltas.items():
			cvt[i] += otRound(delta)

	if 'CFF2' in varfont:
		log.info("Mutating CFF2 table")
		glyphOrder = varfont.getGlyphOrder()
		CFF2 = varfont['CFF2']
		topDict = CFF2.cff.topDictIndex[0]
		vsInstancer = VarStoreInstancer(topDict.VarStore.otVarStore, fvar.axes, loc)
		interpolateFromDeltas = vsInstancer.interpolateFromDeltas
		interpolate_cff2_PrivateDict(topDict, interpolateFromDeltas)
		CFF2.desubroutinize()
		interpolate_cff2_charstrings(topDict, interpolateFromDeltas, glyphOrder)
		interpolate_cff2_metrics(varfont, topDict, glyphOrder, loc)
		del topDict.rawDict['VarStore']
		del topDict.VarStore

	if 'MVAR' in varfont:
		log.info("Mutating MVAR table")
		mvar = varfont['MVAR'].table
		varStoreInstancer = VarStoreInstancer(mvar.VarStore, fvar.axes, loc)
		records = mvar.ValueRecord
		for rec in records:
			mvarTag = rec.ValueTag
			if mvarTag not in MVAR_ENTRIES:
				continue
			tableTag, itemName = MVAR_ENTRIES[mvarTag]
			delta = otRound(varStoreInstancer[rec.VarIdx])
			if not delta:
				continue
			setattr(varfont[tableTag], itemName,
				getattr(varfont[tableTag], itemName) + delta)

	log.info("Mutating FeatureVariations")
	for tableTag in 'GSUB','GPOS':
		if not tableTag in varfont:
			continue
		table = varfont[tableTag].table
		if not hasattr(table, 'FeatureVariations'):
			continue
		variations = table.FeatureVariations
		for record in variations.FeatureVariationRecord:
			applies = True
			for condition in record.ConditionSet.ConditionTable:
				if condition.Format == 1:
					axisIdx = condition.AxisIndex
					axisTag = fvar.axes[axisIdx].axisTag
					Min = condition.FilterRangeMinValue
					Max = condition.FilterRangeMaxValue
					v = loc[axisTag]
					if not (Min <= v <= Max):
						applies = False
				else:
					applies = False
				if not applies:
					break

			if applies:
				assert record.FeatureTableSubstitution.Version == 0x00010000
				for rec in record.FeatureTableSubstitution.SubstitutionRecord:
					table.FeatureList.FeatureRecord[rec.FeatureIndex].Feature = rec.Feature
				break
		del table.FeatureVariations

	if 'GDEF' in varfont and varfont['GDEF'].table.Version >= 0x00010003:
		log.info("Mutating GDEF/GPOS/GSUB tables")
		gdef = varfont['GDEF'].table
		instancer = VarStoreInstancer(gdef.VarStore, fvar.axes, loc)

		merger = MutatorMerger(varfont, instancer)
		merger.mergeTables(varfont, [varfont], ['GDEF', 'GPOS'])

		# Downgrade GDEF.
		del gdef.VarStore
		gdef.Version = 0x00010002
		if gdef.MarkGlyphSetsDef is None:
			del gdef.MarkGlyphSetsDef
			gdef.Version = 0x00010000

		if not (gdef.LigCaretList or
			gdef.MarkAttachClassDef or
			gdef.GlyphClassDef or
			gdef.AttachList or
			(gdef.Version >= 0x00010002 and gdef.MarkGlyphSetsDef)):
			del varfont['GDEF']

	addidef = False
	if glyf:
		for glyph in glyf.glyphs.values():
			if hasattr(glyph, "program"):
				instructions = glyph.program.getAssembly()
				# If GETVARIATION opcode is used in bytecode of any glyph add IDEF
				addidef = any(op.startswith("GETVARIATION") for op in instructions)
				if addidef:
					break
		if overlap:
			for glyph_name in glyf.keys():
				glyph = glyf[glyph_name]
				# Set OVERLAP_COMPOUND bit for compound glyphs
				if glyph.isComposite():
					glyph.components[0].flags |= OVERLAP_COMPOUND
				# Set OVERLAP_SIMPLE bit for simple glyphs
				elif glyph.numberOfContours > 0:
					glyph.flags[0] |= flagOverlapSimple
	if addidef:
		log.info("Adding IDEF to fpgm table for GETVARIATION opcode")
		asm = []
		if 'fpgm' in varfont:
			fpgm = varfont['fpgm']
			asm = fpgm.program.getAssembly()
		else:
			fpgm = newTable('fpgm')
			fpgm.program = ttProgram.Program()
			varfont['fpgm'] = fpgm
		asm.append("PUSHB[000] 145")
		asm.append("IDEF[ ]")
		args = [str(len(loc))]
		for a in fvar.axes:
			args.append(str(floatToFixed(loc[a.axisTag], 14)))
		asm.append("NPUSHW[ ] " + ' '.join(args))
		asm.append("ENDF[ ]")
		fpgm.program.fromAssembly(asm)

		# Change maxp attributes as IDEF is added
		if 'maxp' in varfont:
			maxp = varfont['maxp']
			if hasattr(maxp, "maxInstructionDefs"):
				maxp.maxInstructionDefs += 1
			else:
				setattr(maxp, "maxInstructionDefs", 1)
			if hasattr(maxp, "maxStackElements"):
				maxp.maxStackElements = max(len(loc), maxp.maxStackElements)
			else:
				setattr(maxp, "maxInstructionDefs", len(loc))

	if 'name' in varfont:
		log.info("Pruning name table")
		exclude = {a.axisNameID for a in fvar.axes}
		for i in fvar.instances:
			exclude.add(i.subfamilyNameID)
			exclude.add(i.postscriptNameID)
		if 'ltag' in varfont:
			# Drop the whole 'ltag' table if all its language tags are referenced by
			# name records to be pruned.
			# TODO: prune unused ltag tags and re-enumerate langIDs accordingly
			excludedUnicodeLangIDs = [
				n.langID for n in varfont['name'].names
				if n.nameID in exclude and n.platformID == 0 and n.langID != 0xFFFF
			]
			if set(excludedUnicodeLangIDs) == set(range(len((varfont['ltag'].tags)))):
				del varfont['ltag']
		varfont['name'].names[:] = [
			n for n in varfont['name'].names
			if n.nameID not in exclude
		]

	if "wght" in location and "OS/2" in varfont:
		varfont["OS/2"].usWeightClass = otRound(
			max(1, min(location["wght"], 1000))
		)
	if "wdth" in location:
		wdth = location["wdth"]
		for percent, widthClass in sorted(OS2_WIDTH_CLASS_VALUES.items()):
			if wdth < percent:
				varfont["OS/2"].usWidthClass = widthClass
				break
		else:
			varfont["OS/2"].usWidthClass = 9
	if "slnt" in location and "post" in varfont:
		varfont["post"].italicAngle = max(-90, min(location["slnt"], 90))

	log.info("Removing variable tables")
	for tag in ('avar','cvar','fvar','gvar','HVAR','MVAR','VVAR','STAT'):
		if tag in varfont:
			del varfont[tag]

	return varfont


def main(args=None):
	from fontTools import configLogger
	import argparse

	parser = argparse.ArgumentParser(
		"fonttools varLib.mutator", description="Instantiate a variable font")
	parser.add_argument(
		"input", metavar="INPUT.ttf", help="Input variable TTF file.")
	parser.add_argument(
		"locargs", metavar="AXIS=LOC", nargs="*",
		help="List of space separated locations. A location consist in "
		"the name of a variation axis, followed by '=' and a number. E.g.: "
		" wght=700 wdth=80. The default is the location of the base master.")
	parser.add_argument(
		"-o", "--output", metavar="OUTPUT.ttf", default=None,
		help="Output instance TTF file (default: INPUT-instance.ttf).")
	logging_group = parser.add_mutually_exclusive_group(required=False)
	logging_group.add_argument(
		"-v", "--verbose", action="store_true", help="Run more verbosely.")
	logging_group.add_argument(
		"-q", "--quiet", action="store_true", help="Turn verbosity off.")
	parser.add_argument(
		"--no-overlap",
		dest="overlap",
		action="store_false",
		help="Don't set OVERLAP_SIMPLE/OVERLAP_COMPOUND glyf flags."
	)
	options = parser.parse_args(args)

	varfilename = options.input
	outfile = (
		os.path.splitext(varfilename)[0] + '-instance.ttf'
		if not options.output else options.output)
	configLogger(level=(
		"DEBUG" if options.verbose else
		"ERROR" if options.quiet else
		"INFO"))

	loc = {}
	for arg in options.locargs:
		try:
			tag, val = arg.split('=')
			assert len(tag) <= 4
			loc[tag.ljust(4)] = float(val)
		except (ValueError, AssertionError):
			parser.error("invalid location argument format: %r" % arg)
	log.info("Location: %s", loc)

	log.info("Loading variable font")
	varfont = TTFont(varfilename)

	instantiateVariableFont(varfont, loc, inplace=True, overlap=options.overlap)

	log.info("Saving instance font %s", outfile)
	varfont.save(outfile)


if __name__ == "__main__":
	import sys
	if len(sys.argv) > 1:
		sys.exit(main())
	import doctest
	sys.exit(doctest.testmod().failed)
