from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
from . import DefaultTable

maxpFormat_0_5 = """
		>	# big endian
		tableVersion:           i
		numGlyphs:              H
"""

maxpFormat_1_0_add = """
		>	# big endian
		maxPoints:              H
		maxContours:            H
		maxCompositePoints:     H
		maxCompositeContours:   H
		maxZones:               H
		maxTwilightPoints:      H
		maxStorage:             H
		maxFunctionDefs:        H
		maxInstructionDefs:     H
		maxStackElements:       H
		maxSizeOfInstructions:  H
		maxComponentElements:   H
		maxComponentDepth:      H
"""


class table__m_a_x_p(DefaultTable.DefaultTable):

	dependencies = ['glyf']

	def decompile(self, data, ttFont):
		dummy, data = sstruct.unpack2(maxpFormat_0_5, data, self)
		self.numGlyphs = int(self.numGlyphs)
		if self.tableVersion != 0x00005000:
			dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self)
		assert len(data) == 0

	def compile(self, ttFont):
		if 'glyf' in ttFont:
			if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes:
				self.recalc(ttFont)
		else:
			pass  # CFF
		self.numGlyphs = len(ttFont.getGlyphOrder())
		if self.tableVersion != 0x00005000:
			self.tableVersion = 0x00010000
		data = sstruct.pack(maxpFormat_0_5, self)
		if self.tableVersion == 0x00010000:
			data = data + sstruct.pack(maxpFormat_1_0_add, self)
		return data

	def recalc(self, ttFont):
		"""Recalculate the font bounding box, and most other maxp values except
		for the TT instructions values. Also recalculate the value of bit 1
		of the flags field and the font bounding box of the 'head' table.
		"""
		glyfTable = ttFont['glyf']
		hmtxTable = ttFont['hmtx']
		headTable = ttFont['head']
		self.numGlyphs = len(glyfTable)
		INFINITY = 100000
		xMin = +INFINITY
		yMin = +INFINITY
		xMax = -INFINITY
		yMax = -INFINITY
		maxPoints = 0
		maxContours = 0
		maxCompositePoints = 0
		maxCompositeContours = 0
		maxComponentElements = 0
		maxComponentDepth = 0
		allXMinIsLsb = 1
		for glyphName in ttFont.getGlyphOrder():
			g = glyfTable[glyphName]
			if g.numberOfContours:
				if hmtxTable[glyphName][1] != g.xMin:
					allXMinIsLsb = 0
				xMin = min(xMin, g.xMin)
				yMin = min(yMin, g.yMin)
				xMax = max(xMax, g.xMax)
				yMax = max(yMax, g.yMax)
				if g.numberOfContours > 0:
					nPoints, nContours = g.getMaxpValues()
					maxPoints = max(maxPoints, nPoints)
					maxContours = max(maxContours, nContours)
				else:
					nPoints, nContours, componentDepth = g.getCompositeMaxpValues(glyfTable)
					maxCompositePoints = max(maxCompositePoints, nPoints)
					maxCompositeContours = max(maxCompositeContours, nContours)
					maxComponentElements = max(maxComponentElements, len(g.components))
					maxComponentDepth = max(maxComponentDepth, componentDepth)
		if xMin == +INFINITY:
			headTable.xMin = 0
			headTable.yMin = 0
			headTable.xMax = 0
			headTable.yMax = 0
		else:
			headTable.xMin = xMin
			headTable.yMin = yMin
			headTable.xMax = xMax
			headTable.yMax = yMax
		self.maxPoints = maxPoints
		self.maxContours = maxContours
		self.maxCompositePoints = maxCompositePoints
		self.maxCompositeContours = maxCompositeContours
		self.maxComponentElements = maxComponentElements
		self.maxComponentDepth = maxComponentDepth
		if allXMinIsLsb:
			headTable.flags = headTable.flags | 0x2
		else:
			headTable.flags = headTable.flags & ~0x2

	def testrepr(self):
		items = sorted(self.__dict__.items())
		print(". . . . . . . . .")
		for combo in items:
			print("  %s: %s" % combo)
		print(". . . . . . . . .")

	def toXML(self, writer, ttFont):
		if self.tableVersion != 0x00005000:
			writer.comment("Most of this table will be recalculated by the compiler")
			writer.newline()
		formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5)
		if self.tableVersion != 0x00005000:
			formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add)
			names = names + names_1_0
		for name in names:
			value = getattr(self, name)
			if name == "tableVersion":
				value = hex(value)
			writer.simpletag(name, value=value)
			writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		setattr(self, name, safeEval(attrs["value"]))
