# Source code for fontTools.ttLib.tables.M_E_T_A_

    from fontTools.misc import sstruct
    from fontTools.misc.textTools import byteord, safeEval
    from . import DefaultTable
    import pdb
    import struct

    METAHeaderFormat = """
    		>	# big endian
    		tableVersionMajor:			H
    		tableVersionMinor:			H
    		metaEntriesVersionMajor:	H
    		metaEntriesVersionMinor:	H
    		unicodeVersion:				L
    		metaFlags:					H
    		nMetaRecs:					H
    """
    # This record is followed by nMetaRecs of METAGlyphRecordFormat.
    # This in turn is followd by as many METAStringRecordFormat entries
    # as specified by the METAGlyphRecordFormat entries
    # this is followed by the strings specifried in the  METAStringRecordFormat
    METAGlyphRecordFormat = """
    		>	# big endian
    		glyphID:			H
    		nMetaEntry:			H
    """
    # This record is followd by a variable data length field:
    # 	USHORT or ULONG	hdrOffset
    # Offset from start of META table to the beginning
    # of this glyphs array of ns Metadata string entries.
    # Size determined by metaFlags field
    # METAGlyphRecordFormat entries must be sorted by glyph ID

    METAStringRecordFormat = """
    		>	# big endian
    		labelID:			H
    		stringLen:			H
    """
    # This record is followd by a variable data length field:
    # 	USHORT or ULONG	stringOffset
    # METAStringRecordFormat entries must be sorted in order of labelID
    # There may be more than one entry with the same labelID
    # There may be more than one strign with the same content.

    # Strings shall be Unicode UTF-8 encoded, and null-terminated.

    METALabelDict = {
    	0: "MojikumiX4051", # An integer in the range 1-20
    	1: "UNIUnifiedBaseChars",
    	2: "BaseFontName",
    	3: "Language",
    	4: "CreationDate",
    	5: "FoundryName",
    	6: "FoundryCopyright",
    	7: "OwnerURI",
    	8: "WritingScript",
    	10: "StrokeCount",
    	11: "IndexingRadical",
    }

    def getLabelString(labelID):
    	try:
    		label = METALabelDict[labelID]
    	except KeyError:
    		label = "Unknown label"
    	return str(label)

    class table_M_E_T_A_(DefaultTable.DefaultTable):

    	dependencies = []

    	def decompile(self, data, ttFont):
    		dummy, newData = sstruct.unpack2(METAHeaderFormat, data, self)
    		self.glyphRecords = []
    		for i in range(self.nMetaRecs):
    			glyphRecord, newData = sstruct.unpack2(METAGlyphRecordFormat, newData, GlyphRecord())
    			if self.metaFlags == 0:
    				[glyphRecord.offset] = struct.unpack(">H", newData[:2])
    				newData = newData[2:]
    			elif self.metaFlags == 1:
    				[glyphRecord.offset] = struct.unpack(">H", newData[:4])
    				newData = newData[4:]
    			else:
    				assert 0, "The metaFlags field in the META table header has a value other than 0 or 1 :" + str(self.metaFlags)
    			glyphRecord.stringRecs = []
    			newData = data[glyphRecord.offset:]
    			for j in range(glyphRecord.nMetaEntry):
    				stringRec, newData = sstruct.unpack2(METAStringRecordFormat, newData, StringRecord())
    				if self.metaFlags == 0:
    					[stringRec.offset] = struct.unpack(">H", newData[:2])
    					newData = newData[2:]
    				else:
    					[stringRec.offset] = struct.unpack(">H", newData[:4])
    					newData = newData[4:]
    				stringRec.string = data[stringRec.offset:stringRec.offset + stringRec.stringLen]
    				glyphRecord.stringRecs.append(stringRec)
    			self.glyphRecords.append(glyphRecord)

    	def compile(self, ttFont):
    		offsetOK = 0
    		self.nMetaRecs = len(self.glyphRecords)
    		count = 0
    		while (offsetOK != 1):
    			count = count + 1
    			if count > 4:
    				pdb.set_trace()
    			metaData = sstruct.pack(METAHeaderFormat, self)
    			stringRecsOffset = len(metaData) + self.nMetaRecs * (6 + 2*(self.metaFlags & 1))
    			stringRecSize = (6 + 2*(self.metaFlags & 1))
    			for glyphRec in self.glyphRecords:
    				glyphRec.offset = stringRecsOffset
    				if (glyphRec.offset > 65535) and ((self.metaFlags & 1) == 0):
    					self.metaFlags = self.metaFlags + 1
    					offsetOK = -1
    					break
    				metaData = metaData + glyphRec.compile(self)
    				stringRecsOffset = stringRecsOffset + (glyphRec.nMetaEntry * stringRecSize)
    				# this will be the String Record offset for the next GlyphRecord.
    			if offsetOK == -1:
    				offsetOK = 0
    				continue

    			# metaData now contains the header and all of the GlyphRecords. Its length should bw
    			# the offset to the first StringRecord.
    			stringOffset = stringRecsOffset
    			for glyphRec in self.glyphRecords:
    				assert (glyphRec.offset == len(metaData)), "Glyph record offset did not compile correctly! for rec:" + str(glyphRec)
    				for stringRec in glyphRec.stringRecs:
    					stringRec.offset = stringOffset
    					if (stringRec.offset > 65535) and ((self.metaFlags & 1) == 0):
    						self.metaFlags = self.metaFlags + 1
    						offsetOK = -1
    						break
    					metaData = metaData + stringRec.compile(self)
    					stringOffset = stringOffset + stringRec.stringLen
    			if 	offsetOK == -1:
    				offsetOK = 0
    				continue

    			if ((self.metaFlags & 1) == 1) and (stringOffset < 65536):
    				self.metaFlags = self.metaFlags - 1
    				continue
    			else:
    				offsetOK = 1

    			# metaData now contains the header and all of the GlyphRecords and all of the String Records.
    			# Its length should be the offset to the first string datum.
    			for glyphRec in self.glyphRecords:
    				for stringRec in glyphRec.stringRecs:
    					assert (stringRec.offset == len(metaData)), "String offset did not compile correctly! for string:" + str(stringRec.string)
    					metaData = metaData + stringRec.string

    		return metaData

    	def toXML(self, writer, ttFont):
    		writer.comment("Lengths and number of entries in this table will be recalculated by the compiler")
    		writer.newline()
    		formatstring, names, fixes = sstruct.getformat(METAHeaderFormat)
    		for name in names:
    			value = getattr(self, name)
    			writer.simpletag(name, value=value)
    			writer.newline()
    		for glyphRec in self.glyphRecords:
    			glyphRec.toXML(writer, ttFont)

    	def fromXML(self, name, attrs, content, ttFont):
    		if name == "GlyphRecord":
    			if not hasattr(self, "glyphRecords"):
    				self.glyphRecords = []
    			glyphRec = GlyphRecord()
    			self.glyphRecords.append(glyphRec)
    			for element in content:
    				if isinstance(element, str):
    					continue
    				name, attrs, content = element
    				glyphRec.fromXML(name, attrs, content, ttFont)
    			glyphRec.offset = -1
    			glyphRec.nMetaEntry = len(glyphRec.stringRecs)
    		else:
    			setattr(self, name, safeEval(attrs["value"]))

    class GlyphRecord(object):
    	def __init__(self):
    		self.glyphID = -1
    		self.nMetaEntry = -1
    		self.offset = -1
    		self.stringRecs = []

    	def toXML(self, writer, ttFont):
    		writer.begintag("GlyphRecord")
    		writer.newline()
    		writer.simpletag("glyphID", value=self.glyphID)
    		writer.newline()
    		writer.simpletag("nMetaEntry", value=self.nMetaEntry)
    		writer.newline()
    		for stringRec in self.stringRecs:
    			stringRec.toXML(writer, ttFont)
    		writer.endtag("GlyphRecord")
    		writer.newline()

    	def fromXML(self, name, attrs, content, ttFont):
    		if name == "StringRecord":
    			stringRec = StringRecord()
    			self.stringRecs.append(stringRec)
    			for element in content:
    				if isinstance(element, str):
    					continue
    				stringRec.fromXML(name, attrs, content, ttFont)
    			stringRec.stringLen = len(stringRec.string)
    		else:
    			setattr(self, name, safeEval(attrs["value"]))

    	def compile(self, parentTable):
    		data = sstruct.pack(METAGlyphRecordFormat, self)
    		if parentTable.metaFlags == 0:
    			datum = struct.pack(">H", self.offset)
    		elif parentTable.metaFlags == 1:
    			datum = struct.pack(">L", self.offset)
    		data = data + datum
    		return data

    	def __repr__(self):
    		return "GlyphRecord[ glyphID: " + str(self.glyphID) + ", nMetaEntry: " + str(self.nMetaEntry) + ", offset: " + str(self.offset) + " ]"

    # XXX The following two functions are really broken around UTF-8 vs Unicode

    def mapXMLToUTF8(string):
    	uString = str()
    	strLen = len(string)
    	i = 0
    	while i < strLen:
    		prefixLen = 0
    		if  (string[i:i+3] == "&#x"):
    			prefixLen = 3
    		elif  (string[i:i+7] == "&amp;#x"):
    			prefixLen = 7
    		if prefixLen:
    			i = i+prefixLen
    			j= i
    			while string[i] != ";":
    				i = i+1
    			valStr = string[j:i]

    			uString = uString + chr(eval('0x' + valStr))
    		else:
    			uString = uString + chr(byteord(string[i]))
    		i = i +1

    	return uString.encode('utf_8')

    def mapUTF8toXML(string):
    	uString = string.decode('utf_8')
    	string = ""
    	for uChar in uString:
    		i = ord(uChar)
    		if (i < 0x80) and (i > 0x1F):
    			string = string + uChar
    		else:
    			string = string + "&#x" + hex(i)[2:] + ";"
    	return string

    class StringRecord(object):

    	def toXML(self, writer, ttFont):
    		writer.begintag("StringRecord")
    		writer.newline()
    		writer.simpletag("labelID", value=self.labelID)
    		writer.comment(getLabelString(self.labelID))
    		writer.newline()
    		writer.newline()
    		writer.simpletag("string", value=mapUTF8toXML(self.string))
    		writer.newline()
    		writer.endtag("StringRecord")
    		writer.newline()

    	def fromXML(self, name, attrs, content, ttFont):
    		for element in content:
    			if isinstance(element, str):
    				continue
    			name, attrs, content = element
    			value = attrs["value"]
    			if name == "string":
    				self.string = mapXMLToUTF8(value)
    			else:
    				setattr(self, name, safeEval(value))

    	def compile(self, parentTable):
    		data = sstruct.pack(METAStringRecordFormat, self)
    		if parentTable.metaFlags == 0:
    			datum = struct.pack(">H", self.offset)
    		elif parentTable.metaFlags == 1:
    			datum = struct.pack(">L", self.offset)
    		data = data + datum
    		return data

    	def __repr__(self):
    		return "StringRecord [ labelID: " + str(self.labelID) + " aka " + getLabelString(self.labelID) \
    			+ ", offset: " + str(self.offset) + ", length: " + str(self.stringLen) + ", string: " +self.string + " ]"