from collections import namedtuple
from fontTools.cffLib import (
	maxStackLimit,
	TopDictIndex,
	buildOrder,
	topDictOperators,
	topDictOperators2,
	privateDictOperators,
	privateDictOperators2,
	FDArrayIndex,
	FontDict,
	VarStoreData
)
from io import BytesIO
from fontTools.cffLib.specializer import (
	specializeCommands, commandsToProgram)
from fontTools.ttLib import newTable
from fontTools import varLib
from fontTools.varLib.models import allEqual
from fontTools.misc.roundTools import roundFunc
from fontTools.misc.psCharStrings import T2CharString, T2OutlineExtractor
from fontTools.pens.t2CharStringPen import T2CharStringPen
from functools import partial

from .errors import (
	VarLibCFFDictMergeError, VarLibCFFPointTypeMergeError,
	VarLibCFFHintTypeMergeError,VarLibMergeError)


# Backwards compatibility
MergeDictError = VarLibCFFDictMergeError
MergeTypeError = VarLibCFFPointTypeMergeError


def addCFFVarStore(varFont, varModel, varDataList, masterSupports):
	fvarTable = varFont['fvar']
	axisKeys = [axis.axisTag for axis in fvarTable.axes]
	varTupleList = varLib.builder.buildVarRegionList(masterSupports, axisKeys)
	varStoreCFFV = varLib.builder.buildVarStore(varTupleList, varDataList)

	topDict = varFont['CFF2'].cff.topDictIndex[0]
	topDict.VarStore = VarStoreData(otVarStore=varStoreCFFV)
	if topDict.FDArray[0].vstore is None:
		fdArray = topDict.FDArray
		for fontDict in fdArray:
			if hasattr(fontDict, "Private"):
				fontDict.Private.vstore = topDict.VarStore


def lib_convertCFFToCFF2(cff, otFont):
	# This assumes a decompiled CFF table.
	cff2GetGlyphOrder = cff.otFont.getGlyphOrder
	topDictData = TopDictIndex(None, cff2GetGlyphOrder, None)
	topDictData.items = cff.topDictIndex.items
	cff.topDictIndex = topDictData
	topDict = topDictData[0]
	if hasattr(topDict, 'Private'):
		privateDict = topDict.Private
	else:
		privateDict = None
	opOrder = buildOrder(topDictOperators2)
	topDict.order = opOrder
	topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
	if not hasattr(topDict, "FDArray"):
		fdArray = topDict.FDArray = FDArrayIndex()
		fdArray.strings = None
		fdArray.GlobalSubrs = topDict.GlobalSubrs
		topDict.GlobalSubrs.fdArray = fdArray
		charStrings = topDict.CharStrings
		if charStrings.charStringsAreIndexed:
			charStrings.charStringsIndex.fdArray = fdArray
		else:
			charStrings.fdArray = fdArray
		fontDict = FontDict()
		fontDict.setCFF2(True)
		fdArray.append(fontDict)
		fontDict.Private = privateDict
		privateOpOrder = buildOrder(privateDictOperators2)
		if privateDict is not None:
			for entry in privateDictOperators:
				key = entry[1]
				if key not in privateOpOrder:
					if key in privateDict.rawDict:
						# print "Removing private dict", key
						del privateDict.rawDict[key]
					if hasattr(privateDict, key):
						delattr(privateDict, key)
						# print "Removing privateDict attr", key
	else:
		# clean up the PrivateDicts in the fdArray
		fdArray = topDict.FDArray
		privateOpOrder = buildOrder(privateDictOperators2)
		for fontDict in fdArray:
			fontDict.setCFF2(True)
			for key in list(fontDict.rawDict.keys()):
				if key not in fontDict.order:
					del fontDict.rawDict[key]
					if hasattr(fontDict, key):
						delattr(fontDict, key)

			privateDict = fontDict.Private
			for entry in privateDictOperators:
				key = entry[1]
				if key not in privateOpOrder:
					if key in privateDict.rawDict:
						# print "Removing private dict", key
						del privateDict.rawDict[key]
					if hasattr(privateDict, key):
						delattr(privateDict, key)
						# print "Removing privateDict attr", key
	# Now delete up the decrecated topDict operators from CFF 1.0
	for entry in topDictOperators:
		key = entry[1]
		if key not in opOrder:
			if key in topDict.rawDict:
				del topDict.rawDict[key]
			if hasattr(topDict, key):
				delattr(topDict, key)

	# At this point, the Subrs and Charstrings are all still T2Charstring class
	# easiest to fix this by compiling, then decompiling again
	cff.major = 2
	file = BytesIO()
	cff.compile(file, otFont, isCFF2=True)
	file.seek(0)
	cff.decompile(file, otFont, isCFF2=True)


def convertCFFtoCFF2(varFont):
	# Convert base font to a single master CFF2 font.
	cffTable = varFont['CFF ']
	lib_convertCFFToCFF2(cffTable.cff, varFont)
	newCFF2 = newTable("CFF2")
	newCFF2.cff = cffTable.cff
	varFont['CFF2'] = newCFF2
	del varFont['CFF ']


def conv_to_int(num):
	if isinstance(num, float) and num.is_integer():
		return int(num)
	return num


pd_blend_fields = ("BlueValues", "OtherBlues", "FamilyBlues",
				   "FamilyOtherBlues", "BlueScale", "BlueShift",
				   "BlueFuzz", "StdHW", "StdVW", "StemSnapH",
				   "StemSnapV")


def get_private(regionFDArrays, fd_index, ri, fd_map):
	region_fdArray = regionFDArrays[ri]
	region_fd_map = fd_map[fd_index]
	if ri in region_fd_map:
		region_fdIndex = region_fd_map[ri]
		private = region_fdArray[region_fdIndex].Private
	else:
		private = None
	return private


def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map):
	"""
	I step through the FontDicts in the FDArray of the varfont TopDict.
	For each varfont FontDict:
		step through each key in FontDict.Private.
		For each key, step through each relevant source font Private dict, and
		build a list of values to blend.
	The 'relevant' source fonts are selected by first getting the right
	submodel using vsindex_dict[vsindex]. The indices of the
	subModel.locations are mapped to source font list indices by
	assuming the latter order is the same as the order of the
	var_model.locations. I can then get the index of each subModel
	location in the list of var_model.locations.
	"""

	topDict = top_dicts[0]
	region_top_dicts = top_dicts[1:]
	if hasattr(region_top_dicts[0], 'FDArray'):
		regionFDArrays = [fdTopDict.FDArray for fdTopDict in region_top_dicts]
	else:
		regionFDArrays = [[fdTopDict] for fdTopDict in region_top_dicts]
	for fd_index, font_dict in enumerate(topDict.FDArray):
		private_dict = font_dict.Private
		vsindex = getattr(private_dict, 'vsindex', 0)
		# At the moment, no PrivateDict has a vsindex key, but let's support
		# how it should work. See comment at end of
		# merge_charstrings() - still need to optimize use of vsindex.
		sub_model, _ = vsindex_dict[vsindex]
		master_indices = []
		for loc in sub_model.locations[1:]:
			i = var_model.locations.index(loc) - 1
			master_indices.append(i)
		pds = [private_dict]
		last_pd = private_dict
		for ri in master_indices:
			pd = get_private(regionFDArrays, fd_index, ri, fd_map)
			# If the region font doesn't have this FontDict, just reference
			# the last one used.
			if pd is None:
				pd = last_pd
			else:
				last_pd = pd
			pds.append(pd)
		num_masters = len(pds)
		for key, value in private_dict.rawDict.items():
			dataList = []
			if key not in pd_blend_fields:
				continue
			if isinstance(value, list):
				try:
					values = [pd.rawDict[key] for pd in pds]
				except KeyError:
					print(
						"Warning: {key} in default font Private dict is "
						"missing from another font, and was "
						"discarded.".format(key=key))
					continue
				try:
					values = zip(*values)
				except IndexError:
					raise VarLibCFFDictMergeError(key, value, values)
				"""
				Row 0 contains the first  value from each master.
				Convert each row from absolute values to relative
				values from the previous row.
				e.g for three masters,	a list of values was:
				master 0 OtherBlues = [-217,-205]
				master 1 OtherBlues = [-234,-222]
				master 1 OtherBlues = [-188,-176]
				The call to zip() converts this to:
				[(-217, -234, -188), (-205, -222, -176)]
				and is converted finally to:
				OtherBlues = [[-217, 17.0, 46.0], [-205, 0.0, 0.0]]
				"""
				prev_val_list = [0] * num_masters
				any_points_differ = False
				for val_list in values:
					rel_list = [(val - prev_val_list[i]) for (
							i, val) in enumerate(val_list)]
					if (not any_points_differ) and not allEqual(rel_list):
						any_points_differ = True
					prev_val_list = val_list
					deltas = sub_model.getDeltas(rel_list)
					# For PrivateDict BlueValues, the default font
					# values are absolute, not relative to the prior value.
					deltas[0] = val_list[0]
					dataList.append(deltas)
				# If there are no blend values,then
				# we can collapse the blend lists.
				if not any_points_differ:
					dataList = [data[0] for data in dataList]
			else:
				values = [pd.rawDict[key] for pd in pds]
				if not allEqual(values):
					dataList = sub_model.getDeltas(values)
				else:
					dataList = values[0]

			# Convert numbers with no decimal part to an int
			if isinstance(dataList, list):
				for i, item in enumerate(dataList):
					if isinstance(item, list):
						for j, jtem in enumerate(item):
							dataList[i][j] = conv_to_int(jtem)
					else:
						dataList[i] = conv_to_int(item)
			else:
				dataList = conv_to_int(dataList)

			private_dict.rawDict[key] = dataList


def _cff_or_cff2(font):
	if "CFF " in font:
		return font["CFF "]
	return font["CFF2"]


def getfd_map(varFont, fonts_list):
	""" Since a subset source font may have fewer FontDicts in their
	FDArray than the default font, we have to match up the FontDicts in
	the different fonts . We do this with the FDSelect array, and by
	assuming that the same glyph will reference  matching FontDicts in
	each source font. We return a mapping from fdIndex in the default
	font to a dictionary which maps each master list index of each
	region font to the equivalent fdIndex in the region font."""
	fd_map = {}
	default_font = fonts_list[0]
	region_fonts = fonts_list[1:]
	num_regions = len(region_fonts)
	topDict = _cff_or_cff2(default_font).cff.topDictIndex[0]
	if not hasattr(topDict, 'FDSelect'):
		# All glyphs reference only one FontDict.
		# Map the FD index for regions to index 0.
		fd_map[0] = {ri:0 for ri in range(num_regions)}
		return fd_map

	gname_mapping = {}
	default_fdSelect = topDict.FDSelect
	glyphOrder = default_font.getGlyphOrder()
	for gid, fdIndex in enumerate(default_fdSelect):
		gname_mapping[glyphOrder[gid]] = fdIndex
		if fdIndex not in fd_map:
			fd_map[fdIndex] = {}
	for ri, region_font in enumerate(region_fonts):
		region_glyphOrder = region_font.getGlyphOrder()
		region_topDict = _cff_or_cff2(region_font).cff.topDictIndex[0]
		if not hasattr(region_topDict, 'FDSelect'):
			# All the glyphs share the same FontDict. Pick any glyph.
			default_fdIndex = gname_mapping[region_glyphOrder[0]]
			fd_map[default_fdIndex][ri] = 0
		else:
			region_fdSelect = region_topDict.FDSelect
			for gid, fdIndex in enumerate(region_fdSelect):
				default_fdIndex = gname_mapping[region_glyphOrder[gid]]
				region_map = fd_map[default_fdIndex]
				if ri not in region_map:
					region_map[ri] = fdIndex
	return fd_map


CVarData = namedtuple('CVarData', 'varDataList masterSupports vsindex_dict')
def merge_region_fonts(varFont, model, ordered_fonts_list, glyphOrder):
	topDict = varFont['CFF2'].cff.topDictIndex[0]
	top_dicts = [topDict] + [
					_cff_or_cff2(ttFont).cff.topDictIndex[0]
					for ttFont in ordered_fonts_list[1:]
					]
	num_masters = len(model.mapping)
	cvData = merge_charstrings(glyphOrder, num_masters, top_dicts, model)
	fd_map = getfd_map(varFont, ordered_fonts_list)
	merge_PrivateDicts(top_dicts, cvData.vsindex_dict, model, fd_map)
	addCFFVarStore(varFont, model, cvData.varDataList,
		cvData.masterSupports)


def _get_cs(charstrings, glyphName):
	if glyphName not in charstrings:
		return None
	return charstrings[glyphName]

def _add_new_vsindex(model, key, masterSupports, vsindex_dict,
		vsindex_by_key, varDataList):
	varTupleIndexes = []
	for support in model.supports[1:]:
		if support not in masterSupports:
			masterSupports.append(support)
		varTupleIndexes.append(masterSupports.index(support))
	var_data = varLib.builder.buildVarData(varTupleIndexes, None, False)
	vsindex = len(vsindex_dict)
	vsindex_by_key[key] = vsindex
	vsindex_dict[vsindex] = (model, [key])
	varDataList.append(var_data)
	return vsindex

def merge_charstrings(glyphOrder, num_masters, top_dicts, masterModel):

	vsindex_dict = {}
	vsindex_by_key = {}
	varDataList = []
	masterSupports = []
	default_charstrings = top_dicts[0].CharStrings
	for gid, gname in enumerate(glyphOrder):
		all_cs = [
				_get_cs(td.CharStrings, gname)
				for td in top_dicts]
		if len([gs for gs in all_cs if gs is not None]) == 1:
			continue
		model, model_cs = masterModel.getSubModel(all_cs)
		# create the first pass CFF2 charstring, from
		# the default charstring.
		default_charstring = model_cs[0]
		var_pen = CFF2CharStringMergePen([], gname, num_masters, 0)
		# We need to override outlineExtractor because these
		# charstrings do have widths in the 'program'; we need to drop these
		# values rather than post assertion error for them.
		default_charstring.outlineExtractor = MergeOutlineExtractor
		default_charstring.draw(var_pen)

		# Add the coordinates from all the other regions to the
		# blend lists in the CFF2 charstring.
		region_cs = model_cs[1:]
		for region_idx, region_charstring in enumerate(region_cs, start=1):
			var_pen.restart(region_idx)
			region_charstring.outlineExtractor = MergeOutlineExtractor
			region_charstring.draw(var_pen)

		# Collapse each coordinate list to a blend operator and its args.
		new_cs = var_pen.getCharString(
			private=default_charstring.private,
			globalSubrs=default_charstring.globalSubrs,
			var_model=model, optimize=True)
		default_charstrings[gname] = new_cs

		if (not var_pen.seen_moveto) or ('blend' not in new_cs.program):
			# If this is not a marking glyph, or if there are no blend
			# arguments, then we can use vsindex 0. No need to
			# check if we need a new vsindex.
			continue

		# If the charstring required a new model, create
		# a VarData table to go with, and set vsindex.
		key = tuple(v is not None for v in all_cs)
		try:
			vsindex = vsindex_by_key[key]
		except KeyError:
			vsindex = _add_new_vsindex(model, key, masterSupports, vsindex_dict,
				vsindex_by_key, varDataList)
		# We do not need to check for an existing new_cs.private.vsindex,
		# as we know it doesn't exist yet.
		if vsindex != 0:
			new_cs.program[:0] = [vsindex, 'vsindex']

	# If there is no variation in any of the charstrings, then vsindex_dict
	# never gets built. This could still be needed if there is variation
	# in the PrivatDict, so we will build the default data for vsindex = 0.
	if not vsindex_dict:
		key = (True,) * num_masters
		_add_new_vsindex(masterModel, key, masterSupports, vsindex_dict,
			vsindex_by_key, varDataList)
	cvData = CVarData(varDataList=varDataList, masterSupports=masterSupports,
						vsindex_dict=vsindex_dict)
	# XXX To do: optimize use of vsindex between the PrivateDicts and
	# charstrings
	return cvData


class CFFToCFF2OutlineExtractor(T2OutlineExtractor):
	""" This class is used to remove the initial width from the CFF
	charstring without trying to add the width to self.nominalWidthX,
	which is None. """
	def popallWidth(self, evenOdd=0):
		args = self.popall()
		if not self.gotWidth:
			if evenOdd ^ (len(args) % 2):
				args = args[1:]
			self.width = self.defaultWidthX
			self.gotWidth = 1
		return args


class MergeOutlineExtractor(CFFToCFF2OutlineExtractor):
	""" Used to extract the charstring commands - including hints - from a
	CFF charstring in order to merge it as another set of region data
	into a CFF2 variable font charstring."""

	def __init__(self, pen, localSubrs, globalSubrs,
			nominalWidthX, defaultWidthX, private=None):
		super().__init__(pen, localSubrs,
			globalSubrs, nominalWidthX, defaultWidthX, private)

	def countHints(self):
		args = self.popallWidth()
		self.hintCount = self.hintCount + len(args) // 2
		return args

	def _hint_op(self, type, args):
		self.pen.add_hint(type, args)

	def op_hstem(self, index):
		args = self.countHints()
		self._hint_op('hstem', args)

	def op_vstem(self, index):
		args = self.countHints()
		self._hint_op('vstem', args)

	def op_hstemhm(self, index):
		args = self.countHints()
		self._hint_op('hstemhm', args)

	def op_vstemhm(self, index):
		args = self.countHints()
		self._hint_op('vstemhm', args)

	def _get_hintmask(self, index):
		if not self.hintMaskBytes:
			args = self.countHints()
			if args:
				self._hint_op('vstemhm', args)
			self.hintMaskBytes = (self.hintCount + 7) // 8
		hintMaskBytes, index = self.callingStack[-1].getBytes(index,
			self.hintMaskBytes)
		return index, hintMaskBytes

	def op_hintmask(self, index):
		index, hintMaskBytes = self._get_hintmask(index)
		self.pen.add_hintmask('hintmask', [hintMaskBytes])
		return hintMaskBytes, index

	def op_cntrmask(self, index):
		index, hintMaskBytes = self._get_hintmask(index)
		self.pen.add_hintmask('cntrmask', [hintMaskBytes])
		return hintMaskBytes, index


class CFF2CharStringMergePen(T2CharStringPen):
	"""Pen to merge Type 2 CharStrings.
	"""
	def __init__(
				self, default_commands, glyphName, num_masters, master_idx,
				roundTolerance=0.5):
		super().__init__(
							width=None,
							glyphSet=None, CFF2=True,
							roundTolerance=roundTolerance)
		self.pt_index = 0
		self._commands = default_commands
		self.m_index = master_idx
		self.num_masters = num_masters
		self.prev_move_idx = 0
		self.seen_moveto = False
		self.glyphName = glyphName
		self.round = roundFunc(roundTolerance, round=round)

	def add_point(self, point_type, pt_coords):
		if self.m_index == 0:
			self._commands.append([point_type, [pt_coords]])
		else:
			cmd = self._commands[self.pt_index]
			if cmd[0] != point_type:
				raise VarLibCFFPointTypeMergeError(
									point_type,
									self.pt_index, len(cmd[1]),
									cmd[0], self.glyphName)
			cmd[1].append(pt_coords)
		self.pt_index += 1

	def add_hint(self, hint_type, args):
		if self.m_index == 0:
			self._commands.append([hint_type, [args]])
		else:
			cmd = self._commands[self.pt_index]
			if cmd[0] != hint_type:
				raise VarLibCFFHintTypeMergeError(hint_type, self.pt_index, len(cmd[1]),
					cmd[0], self.glyphName)
			cmd[1].append(args)
		self.pt_index += 1

	def add_hintmask(self, hint_type, abs_args):
		# For hintmask, fonttools.cffLib.specializer.py expects
		# each of these to be represented by two sequential commands:
		# first holding only the operator name, with an empty arg list,
		# second with an empty string as the op name, and the mask arg list.
		if self.m_index == 0:
			self._commands.append([hint_type, []])
			self._commands.append(["", [abs_args]])
		else:
			cmd = self._commands[self.pt_index]
			if cmd[0] != hint_type:
				raise VarLibCFFHintTypeMergeError(hint_type, self.pt_index, len(cmd[1]),
					cmd[0], self.glyphName)
			self.pt_index += 1
			cmd = self._commands[self.pt_index]
			cmd[1].append(abs_args)
		self.pt_index += 1

	def _moveTo(self, pt):
		if not self.seen_moveto:
			self.seen_moveto = True
		pt_coords = self._p(pt)
		self.add_point('rmoveto', pt_coords)
		# I set prev_move_idx here because add_point()
		# can change self.pt_index.
		self.prev_move_idx = self.pt_index - 1

	def _lineTo(self, pt):
		pt_coords = self._p(pt)
		self.add_point('rlineto', pt_coords)

	def _curveToOne(self, pt1, pt2, pt3):
		_p = self._p
		pt_coords = _p(pt1)+_p(pt2)+_p(pt3)
		self.add_point('rrcurveto', pt_coords)

	def _closePath(self):
		pass

	def _endPath(self):
		pass

	def restart(self, region_idx):
		self.pt_index = 0
		self.m_index = region_idx
		self._p0 = (0, 0)

	def getCommands(self):
		return self._commands

	def reorder_blend_args(self, commands, get_delta_func):
		"""
		We first re-order the master coordinate values.
		For a moveto to lineto, the args are now arranged as:
			[ [master_0 x,y], [master_1 x,y], [master_2 x,y] ]
		We re-arrange this to
		[	[master_0 x, master_1 x, master_2 x],
			[master_0 y, master_1 y, master_2 y]
		]
		If the master values are all the same, we collapse the list to
		as single value instead of a list.

		We then convert this to:
		[ [master_0 x] + [x delta tuple] + [numBlends=1]
		  [master_0 y] + [y delta tuple] + [numBlends=1]
		]
		"""
		for cmd in commands:
			# arg[i] is the set of arguments for this operator from master i.
			args = cmd[1]
			m_args = zip(*args)
			# m_args[n] is now all num_master args for the i'th argument
			# for this operation.
			cmd[1] = list(m_args)
		lastOp = None
		for cmd in commands:
			op = cmd[0]
			# masks are represented by two cmd's: first has only op names,
			# second has only args.
			if lastOp in ['hintmask', 'cntrmask']:
				coord = list(cmd[1])
				if not allEqual(coord):
					raise VarLibMergeError("Hintmask values cannot differ between source fonts.")
				cmd[1] = [coord[0][0]]
			else:
				coords = cmd[1]
				new_coords = []
				for coord in coords:
					if allEqual(coord):
						new_coords.append(coord[0])
					else:
						# convert to deltas
						deltas = get_delta_func(coord)[1:]
						coord = [coord[0]] + deltas
						new_coords.append(coord)
				cmd[1] = new_coords
			lastOp = op
		return commands

	def getCharString(
					self, private=None, globalSubrs=None,
					var_model=None, optimize=True):
		commands = self._commands
		commands = self.reorder_blend_args(commands, partial (var_model.getDeltas, round=self.round))
		if optimize:
			commands = specializeCommands(
						commands, generalizeFirst=False,
						maxstack=maxStackLimit)
		program = commandsToProgram(commands)
		charString = T2CharString(
						program=program, private=private,
						globalSubrs=globalSubrs)
		return charString
