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

$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85
"""
from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed
from fontTools.misc.roundTools import otRound
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 = otRound(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']
		hMetrics = varfont['hmtx'].metrics
		vMetrics = getattr(varfont.get('vmtx'), 'metrics', None)
		# 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, hMetrics, vMetrics)
			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, hMetrics, vMetrics)
					delta = iup_delta(delta, origCoords, g.endPts)
				coordinates += GlyphCoordinates(delta) * scalar
			glyf._setCoordinates(glyphname, coordinates, hMetrics, vMetrics)
	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 getattr(table, 'FeatureVariations', None):
			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']
			setattr(maxp, "maxInstructionDefs", 1 + getattr(maxp, "maxInstructionDefs", 0))
			setattr(maxp, "maxStackElements", max(len(loc), getattr(maxp, "maxStackElements", 0)))

	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):
	"""Instantiate a variation font"""
	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)
