# Copyright 2013 Google, Inc. All Rights Reserved.
#
# Google Author(s): Behdad Esfahbod

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


class table_C_O_L_R_(DefaultTable.DefaultTable):

	""" This table is structured so that you can treat it like a dictionary keyed by glyph name.

	``ttFont['COLR'][<glyphName>]`` will return the color layers for any glyph.

	``ttFont['COLR'][<glyphName>] = <value>`` will set the color layers for any glyph.
	"""

	@staticmethod
	def _decompileColorLayersV0(table):
		if not table.LayerRecordArray:
			return {}
		colorLayerLists = {}
		layerRecords = table.LayerRecordArray.LayerRecord
		numLayerRecords = len(layerRecords)
		for baseRec in table.BaseGlyphRecordArray.BaseGlyphRecord:
			baseGlyph = baseRec.BaseGlyph
			firstLayerIndex = baseRec.FirstLayerIndex
			numLayers = baseRec.NumLayers
			assert (firstLayerIndex + numLayers <= numLayerRecords)
			layers = []
			for i in range(firstLayerIndex, firstLayerIndex+numLayers):
				layerRec = layerRecords[i]
				layers.append(
					LayerRecord(layerRec.LayerGlyph, layerRec.PaletteIndex)
				)
			colorLayerLists[baseGlyph] = layers
		return colorLayerLists

	def _toOTTable(self, ttFont):
		from . import otTables
		from fontTools.colorLib.builder import populateCOLRv0

		tableClass = getattr(otTables, self.tableTag)
		table = tableClass()
		table.Version = self.version

		populateCOLRv0(
			table,
			{
				baseGlyph: [(layer.name, layer.colorID) for layer in layers]
				for baseGlyph, layers in self.ColorLayers.items()
			},
			glyphMap=ttFont.getReverseGlyphMap(rebuild=True),
		)
		return table

	def decompile(self, data, ttFont):
		from .otBase import OTTableReader
		from . import otTables

		# We use otData to decompile, but we adapt the decompiled otTables to the
		# existing COLR v0 API for backward compatibility.
		reader = OTTableReader(data, tableTag=self.tableTag)
		tableClass = getattr(otTables, self.tableTag)
		table = tableClass()
		table.decompile(reader, ttFont)

		self.version = table.Version
		if self.version == 0:
			self.ColorLayers = self._decompileColorLayersV0(table)
		else:
			# for new versions, keep the raw otTables around
			self.table = table

	def compile(self, ttFont):
		from .otBase import OTTableWriter

		if hasattr(self, "table"):
			table = self.table
		else:
			table = self._toOTTable(ttFont)

		writer = OTTableWriter(tableTag=self.tableTag)
		table.compile(writer, ttFont)
		return writer.getAllData()

	def toXML(self, writer, ttFont):
		if hasattr(self, "table"):
			self.table.toXML2(writer, ttFont)
		else:
			writer.simpletag("version", value=self.version)
			writer.newline()
			for baseGlyph in sorted(self.ColorLayers.keys(), key=ttFont.getGlyphID):
				writer.begintag("ColorGlyph", name=baseGlyph)
				writer.newline()
				for layer in self.ColorLayers[baseGlyph]:
					layer.toXML(writer, ttFont)
				writer.endtag("ColorGlyph")
				writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		if name == "version":  # old COLR v0 API
			setattr(self, name, safeEval(attrs["value"]))
		elif name == "ColorGlyph":
			if not hasattr(self, "ColorLayers"):
				self.ColorLayers = {}
			glyphName = attrs["name"]
			for element in content:
				if isinstance(element, str):
					continue
			layers = []
			for element in content:
				if isinstance(element, str):
					continue
				layer = LayerRecord()
				layer.fromXML(element[0], element[1], element[2], ttFont)
				layers.append (layer)
			self.ColorLayers[glyphName] = layers
		else:  # new COLR v1 API
			from . import otTables

			if not hasattr(self, "table"):
				tableClass = getattr(otTables, self.tableTag)
				self.table = tableClass()
			self.table.fromXML(name, attrs, content, ttFont)
			self.table.populateDefaults()
			self.version = self.table.Version

	def __getitem__(self, glyphName):
		if not isinstance(glyphName, str):
			raise TypeError(f"expected str, found {type(glyphName).__name__}")
		return self.ColorLayers[glyphName]

	def __setitem__(self, glyphName, value):
		if not isinstance(glyphName, str):
			raise TypeError(f"expected str, found {type(glyphName).__name__}")
		if value is not None:
			self.ColorLayers[glyphName] = value
		elif glyphName in self.ColorLayers:
			del self.ColorLayers[glyphName]

	def __delitem__(self, glyphName):
		del self.ColorLayers[glyphName]

class LayerRecord(object):

	def __init__(self, name=None, colorID=None):
		self.name = name
		self.colorID = colorID

	def toXML(self, writer, ttFont):
		writer.simpletag("layer", name=self.name, colorID=self.colorID)
		writer.newline()

	def fromXML(self, eltname, attrs, content, ttFont):
		for (name, value) in attrs.items():
			if name == "name":
				setattr(self, name, value)
			else:
				setattr(self, name, safeEval(value))
