#!/usr/bin/python

# FontDame-to-FontTools for OpenType Layout tables
#
# Source language spec is available at:
# http://monotype.github.io/OpenType_Table_Source/otl_source.html
# https://github.com/Monotype/OpenType_Table_Source/

from __future__ import print_function, division, absolute_import
from __future__ import unicode_literals
from fontTools.misc.py23 import *
from fontTools import ttLib
from fontTools.ttLib.tables._c_m_a_p import cmap_classes
from fontTools.ttLib.tables import otTables as ot
from fontTools.ttLib.tables.otBase import ValueRecord, valueRecordFormatDict
from fontTools.otlLib import builder as otl
from contextlib import contextmanager
from operator import setitem
import logging

class MtiLibError(Exception): pass
class ReferenceNotFoundError(MtiLibError): pass
class FeatureNotFoundError(ReferenceNotFoundError): pass
class LookupNotFoundError(ReferenceNotFoundError): pass


log = logging.getLogger("fontTools.mtiLib")


def makeGlyph(s):
	if s[:2] in ['U ', 'u ']:
		return ttLib.TTFont._makeGlyphName(int(s[2:], 16))
	elif s[:2] == '# ':
		return "glyph%.5d" % int(s[2:])
	assert s.find(' ') < 0, "Space found in glyph name: %s" % s
	assert s, "Glyph name is empty"
	return s

def makeGlyphs(l):
	return [makeGlyph(g) for g in l]

def mapLookup(sym, mapping):
	# Lookups are addressed by name.  So resolved them using a map if available.
	# Fallback to parsing as lookup index if a map isn't provided.
	if mapping is not None:
		try:
			idx = mapping[sym]
		except KeyError:
			raise LookupNotFoundError(sym)
	else:
		idx = int(sym)
	return idx

def mapFeature(sym, mapping):
	# Features are referenced by index according the spec.  So, if symbol is an
	# integer, use it directly.  Otherwise look up in the map if provided.
	try:
		idx = int(sym)
	except ValueError:
		try:
			idx = mapping[sym]
		except KeyError:
			raise FeatureNotFoundError(sym)
	return idx

def setReference(mapper, mapping, sym, setter, collection, key):
	try:
		mapped = mapper(sym, mapping)
	except ReferenceNotFoundError as e:
		try:
			if mapping is not None:
				mapping.addDeferredMapping(lambda ref: setter(collection, key, ref), sym, e)
				return
		except AttributeError:
			pass
		raise
	setter(collection, key, mapped)

class DeferredMapping(dict):

	def __init__(self):
		self._deferredMappings = []

	def addDeferredMapping(self, setter, sym, e):
		log.debug("Adding deferred mapping for symbol '%s' %s", sym, type(e).__name__)
		self._deferredMappings.append((setter,sym, e))

	def applyDeferredMappings(self):
		for setter,sym,e in self._deferredMappings:
			log.debug("Applying deferred mapping for symbol '%s' %s", sym, type(e).__name__)
			try:
				mapped = self[sym]
			except KeyError:
				raise e
			setter(mapped)
			log.debug("Set to %s", mapped)
		self._deferredMappings = []


def parseScriptList(lines, featureMap=None):
	self = ot.ScriptList()
	records = []
	with lines.between('script table'):
		for line in lines:
			while len(line) < 4:
				line.append('')
			scriptTag, langSysTag, defaultFeature, features = line
			log.debug("Adding script %s language-system %s", scriptTag, langSysTag)

			langSys = ot.LangSys()
			langSys.LookupOrder = None
			if defaultFeature:
				setReference(mapFeature, featureMap, defaultFeature, setattr, langSys, 'ReqFeatureIndex')
			else:
				langSys.ReqFeatureIndex = 0xFFFF
			syms = stripSplitComma(features)
			langSys.FeatureIndex = theList = [3] * len(syms)
			for i,sym in enumerate(syms):
				setReference(mapFeature, featureMap, sym, setitem, theList, i)
			langSys.FeatureCount = len(langSys.FeatureIndex)

			script = [s for s in records if s.ScriptTag == scriptTag]
			if script:
				script = script[0].Script
			else:
				scriptRec = ot.ScriptRecord()
				scriptRec.ScriptTag = scriptTag
				scriptRec.Script = ot.Script()
				records.append(scriptRec)
				script = scriptRec.Script
				script.DefaultLangSys = None
				script.LangSysRecord = []
				script.LangSysCount = 0

			if langSysTag == 'default':
				script.DefaultLangSys = langSys
			else:
				langSysRec = ot.LangSysRecord()
				langSysRec.LangSysTag = langSysTag + ' '*(4 - len(langSysTag))
				langSysRec.LangSys = langSys
				script.LangSysRecord.append(langSysRec)
				script.LangSysCount = len(script.LangSysRecord)

	for script in records:
		script.Script.LangSysRecord = sorted(script.Script.LangSysRecord, key=lambda rec: rec.LangSysTag)
	self.ScriptRecord = sorted(records, key=lambda rec: rec.ScriptTag)
	self.ScriptCount = len(self.ScriptRecord)
	return self

def parseFeatureList(lines, lookupMap=None, featureMap=None):
	self = ot.FeatureList()
	self.FeatureRecord = []
	with lines.between('feature table'):
		for line in lines:
			name, featureTag, lookups = line
			if featureMap is not None:
				assert name not in featureMap, "Duplicate feature name: %s" % name
				featureMap[name] = len(self.FeatureRecord)
			# If feature name is integer, make sure it matches its index.
			try:
				assert int(name) == len(self.FeatureRecord), "%d %d" % (name, len(self.FeatureRecord))
			except ValueError:
				pass
			featureRec = ot.FeatureRecord()
			featureRec.FeatureTag = featureTag
			featureRec.Feature = ot.Feature()
			self.FeatureRecord.append(featureRec)
			feature = featureRec.Feature
			feature.FeatureParams = None
			syms = stripSplitComma(lookups)
			feature.LookupListIndex = theList = [None] * len(syms)
			for i,sym in enumerate(syms):
				setReference(mapLookup, lookupMap, sym, setitem, theList, i)
			feature.LookupCount = len(feature.LookupListIndex)

	self.FeatureCount = len(self.FeatureRecord)
	return self

def parseLookupFlags(lines):
	flags = 0
	filterset = None
	allFlags = [
		'righttoleft',
		'ignorebaseglyphs',
		'ignoreligatures',
		'ignoremarks',
		'markattachmenttype',
		'markfiltertype',
	]
	while lines.peeks()[0].lower() in allFlags:
		line = next(lines)
		flag = {
			'righttoleft':		0x0001,
			'ignorebaseglyphs':	0x0002,
			'ignoreligatures':	0x0004,
			'ignoremarks':		0x0008,
			}.get(line[0].lower())
		if flag:
			assert line[1].lower() in ['yes', 'no'], line[1]
			if line[1].lower() == 'yes':
				flags |= flag
			continue
		if line[0].lower() == 'markattachmenttype':
			flags |= int(line[1]) << 8
			continue
		if line[0].lower() == 'markfiltertype':
			flags |= 0x10
			filterset = int(line[1])
	return flags, filterset

def parseSingleSubst(lines, font, _lookupMap=None):
	mapping = {}
	for line in lines:
		assert len(line) == 2, line
		line = makeGlyphs(line)
		mapping[line[0]] = line[1]
	return otl.buildSingleSubstSubtable(mapping)

def parseMultiple(lines, font, _lookupMap=None):
	mapping = {}
	for line in lines:
		line = makeGlyphs(line)
		mapping[line[0]] = line[1:]
	return otl.buildMultipleSubstSubtable(mapping)

def parseAlternate(lines, font, _lookupMap=None):
	mapping = {}
	for line in lines:
		line = makeGlyphs(line)
		mapping[line[0]] = line[1:]
	return otl.buildAlternateSubstSubtable(mapping)

def parseLigature(lines, font, _lookupMap=None):
	mapping = {}
	for line in lines:
		assert len(line) >= 2, line
		line = makeGlyphs(line)
		mapping[tuple(line[1:])] = line[0]
	return otl.buildLigatureSubstSubtable(mapping)

def parseSinglePos(lines, font, _lookupMap=None):
	values = {}
	for line in lines:
		assert len(line) == 3, line
		w = line[0].title().replace(' ', '')
		assert w in valueRecordFormatDict
		g = makeGlyph(line[1])
		v = int(line[2])
		if g not in values:
			values[g] = ValueRecord()
		assert not hasattr(values[g], w), (g, w)
		setattr(values[g], w, v)
	return otl.buildSinglePosSubtable(values, font.getReverseGlyphMap())

def parsePair(lines, font, _lookupMap=None):
	self = ot.PairPos()
	self.ValueFormat1 = self.ValueFormat2 = 0
	typ = lines.peeks()[0].split()[0].lower()
	if typ in ('left', 'right'):
		self.Format = 1
		values = {}
		for line in lines:
			assert len(line) == 4, line
			side = line[0].split()[0].lower()
			assert side in ('left', 'right'), side
			what = line[0][len(side):].title().replace(' ', '')
			mask = valueRecordFormatDict[what][0]
			glyph1, glyph2 = makeGlyphs(line[1:3])
			value = int(line[3])
			if not glyph1 in values: values[glyph1] = {}
			if not glyph2 in values[glyph1]: values[glyph1][glyph2] = (ValueRecord(),ValueRecord())
			rec2 = values[glyph1][glyph2]
			if side == 'left':
				self.ValueFormat1 |= mask
				vr = rec2[0]
			else:
				self.ValueFormat2 |= mask
				vr = rec2[1]
			assert not hasattr(vr, what), (vr, what)
			setattr(vr, what, value)
		self.Coverage = makeCoverage(set(values.keys()), font)
		self.PairSet = []
		for glyph1 in self.Coverage.glyphs:
			values1 = values[glyph1]
			pairset = ot.PairSet()
			records = pairset.PairValueRecord = []
			for glyph2 in sorted(values1.keys(), key=font.getGlyphID):
				values2 = values1[glyph2]
				pair = ot.PairValueRecord()
				pair.SecondGlyph = glyph2
				pair.Value1 = values2[0]
				pair.Value2 = values2[1] if self.ValueFormat2 else None
				records.append(pair)
			pairset.PairValueCount = len(pairset.PairValueRecord)
			self.PairSet.append(pairset)
		self.PairSetCount = len(self.PairSet)
	elif typ.endswith('class'):
		self.Format = 2
		classDefs = [None, None]
		while lines.peeks()[0].endswith("class definition begin"):
			typ = lines.peek()[0][:-len("class definition begin")].lower()
			idx,klass = {
				'first':	(0,ot.ClassDef1),
				'second':	(1,ot.ClassDef2),
			}[typ]
			assert classDefs[idx] is None
			classDefs[idx] = parseClassDef(lines, font, klass=klass)
		self.ClassDef1, self.ClassDef2 = classDefs
		self.Class1Count, self.Class2Count = (1+max(c.classDefs.values()) for c in classDefs)
		self.Class1Record = [ot.Class1Record() for i in range(self.Class1Count)]
		for rec1 in self.Class1Record:
			rec1.Class2Record = [ot.Class2Record() for j in range(self.Class2Count)]
			for rec2 in rec1.Class2Record:
				rec2.Value1 = ValueRecord()
				rec2.Value2 = ValueRecord()
		for line in lines:
			assert len(line) == 4, line
			side = line[0].split()[0].lower()
			assert side in ('left', 'right'), side
			what = line[0][len(side):].title().replace(' ', '')
			mask = valueRecordFormatDict[what][0]
			class1, class2, value = (int(x) for x in line[1:4])
			rec2 = self.Class1Record[class1].Class2Record[class2]
			if side == 'left':
				self.ValueFormat1 |= mask
				vr = rec2.Value1
			else:
				self.ValueFormat2 |= mask
				vr = rec2.Value2
			assert not hasattr(vr, what), (vr, what)
			setattr(vr, what, value)
		for rec1 in self.Class1Record:
			for rec2 in rec1.Class2Record:
				rec2.Value1 = ValueRecord(self.ValueFormat1, rec2.Value1)
				rec2.Value2 = ValueRecord(self.ValueFormat2, rec2.Value2) \
						if self.ValueFormat2 else None

		self.Coverage = makeCoverage(set(self.ClassDef1.classDefs.keys()), font)
	else:
		assert 0, typ
	return self

def parseKernset(lines, font, _lookupMap=None):
	typ = lines.peeks()[0].split()[0].lower()
	if typ in ('left', 'right'):
		with lines.until(("firstclass definition begin", "secondclass definition begin")):
			return parsePair(lines, font)
	return parsePair(lines, font)

def makeAnchor(data, klass=ot.Anchor):
	assert len(data) <= 2
	anchor = klass()
	anchor.Format = 1
	anchor.XCoordinate,anchor.YCoordinate = intSplitComma(data[0])
	if len(data) > 1 and data[1] != '':
		anchor.Format = 2
		anchor.AnchorPoint = int(data[1])
	return anchor

def parseCursive(lines, font, _lookupMap=None):
	records = {}
	for line in lines:
		assert len(line) in [3,4], line
		idx,klass = {
			'entry':	(0,ot.EntryAnchor),
			'exit':		(1,ot.ExitAnchor),
		}[line[0]]
		glyph = makeGlyph(line[1])
		if glyph not in records:
			records[glyph] = [None,None]
		assert records[glyph][idx] is None, (glyph, idx)
		records[glyph][idx] = makeAnchor(line[2:], klass)
	return otl.buildCursivePosSubtable(records, font.getReverseGlyphMap())

def makeMarkRecords(data, coverage, c):
	records = []
	for glyph in coverage.glyphs:
		klass, anchor = data[glyph]
		record = c.MarkRecordClass()
		record.Class = klass
		setattr(record, c.MarkAnchor, anchor)
		records.append(record)
	return records

def makeBaseRecords(data, coverage, c, classCount):
	records = []
	idx = {}
	for glyph in coverage.glyphs:
		idx[glyph] = len(records)
		record = c.BaseRecordClass()
		anchors = [None] * classCount
		setattr(record, c.BaseAnchor, anchors)
		records.append(record)
	for (glyph,klass),anchor in data.items():
		record = records[idx[glyph]]
		anchors = getattr(record, c.BaseAnchor)
		assert anchors[klass] is None, (glyph, klass)
		anchors[klass] = anchor
	return records

def makeLigatureRecords(data, coverage, c, classCount):
	records = [None] * len(coverage.glyphs)
	idx = {g:i for i,g in enumerate(coverage.glyphs)}

	for (glyph,klass,compIdx,compCount),anchor in data.items():
		record = records[idx[glyph]]
		if record is None:
			record = records[idx[glyph]] = ot.LigatureAttach()
			record.ComponentCount = compCount
			record.ComponentRecord = [ot.ComponentRecord() for i in range(compCount)]
			for compRec in record.ComponentRecord:
				compRec.LigatureAnchor = [None] * classCount
		assert record.ComponentCount == compCount, (glyph, record.ComponentCount, compCount)

		anchors = record.ComponentRecord[compIdx - 1].LigatureAnchor
		assert anchors[klass] is None, (glyph, compIdx, klass)
		anchors[klass] = anchor
	return records

def parseMarkToSomething(lines, font, c):
	self = c.Type()
	self.Format = 1
	markData = {}
	baseData = {}
	Data = {
		'mark':		(markData, c.MarkAnchorClass),
		'base':		(baseData, c.BaseAnchorClass),
		'ligature':	(baseData, c.BaseAnchorClass),
	}
	maxKlass = 0
	for line in lines:
		typ = line[0]
		assert typ in ('mark', 'base', 'ligature')
		glyph = makeGlyph(line[1])
		data, anchorClass = Data[typ]
		extraItems = 2 if typ == 'ligature' else 0
		extras = tuple(int(i) for i in line[2:2+extraItems])
		klass = int(line[2+extraItems])
		anchor = makeAnchor(line[3+extraItems:], anchorClass)
		if typ == 'mark':
			key,value = glyph,(klass,anchor)
		else:
			key,value = ((glyph,klass)+extras),anchor
		assert key not in data, key
		data[key] = value
		maxKlass = max(maxKlass, klass)

	# Mark
	markCoverage = makeCoverage(set(markData.keys()), font, c.MarkCoverageClass)
	markArray = c.MarkArrayClass()
	markRecords = makeMarkRecords(markData, markCoverage, c)
	setattr(markArray, c.MarkRecord, markRecords)
	setattr(markArray, c.MarkCount, len(markRecords))
	setattr(self, c.MarkCoverage, markCoverage)
	setattr(self, c.MarkArray, markArray)
	self.ClassCount = maxKlass + 1

	# Base
	self.classCount = 0 if not baseData else 1+max(k[1] for k,v in baseData.items())
	baseCoverage = makeCoverage(set([k[0] for k in baseData.keys()]), font, c.BaseCoverageClass)
	baseArray = c.BaseArrayClass()
	if c.Base == 'Ligature':
		baseRecords = makeLigatureRecords(baseData, baseCoverage, c, self.classCount)
	else:
		baseRecords = makeBaseRecords(baseData, baseCoverage, c, self.classCount)
	setattr(baseArray, c.BaseRecord, baseRecords)
	setattr(baseArray, c.BaseCount, len(baseRecords))
	setattr(self, c.BaseCoverage, baseCoverage)
	setattr(self, c.BaseArray, baseArray)

	return self

class MarkHelper(object):
	def __init__(self):
		for Which in ('Mark', 'Base'):
			for What in ('Coverage', 'Array', 'Count', 'Record', 'Anchor'):
				key = Which + What
				if Which == 'Mark' and What in ('Count', 'Record', 'Anchor'):
					value = key
				else:
					value = getattr(self, Which) + What
				if value == 'LigatureRecord':
					value = 'LigatureAttach'
				setattr(self, key, value)
				if What != 'Count':
					klass = getattr(ot, value)
					setattr(self, key+'Class', klass)

class MarkToBaseHelper(MarkHelper):
	Mark = 'Mark'
	Base = 'Base'
	Type = ot.MarkBasePos
class MarkToMarkHelper(MarkHelper):
	Mark = 'Mark1'
	Base = 'Mark2'
	Type = ot.MarkMarkPos
class MarkToLigatureHelper(MarkHelper):
	Mark = 'Mark'
	Base = 'Ligature'
	Type = ot.MarkLigPos

def parseMarkToBase(lines, font, _lookupMap=None):
	return parseMarkToSomething(lines, font, MarkToBaseHelper())
def parseMarkToMark(lines, font, _lookupMap=None):
	return parseMarkToSomething(lines, font, MarkToMarkHelper())
def parseMarkToLigature(lines, font, _lookupMap=None):
	return parseMarkToSomething(lines, font, MarkToLigatureHelper())

def stripSplitComma(line):
	return [s.strip() for s in line.split(',')] if line else []

def intSplitComma(line):
	return [int(i) for i in line.split(',')] if line else []

# Copied from fontTools.subset
class ContextHelper(object):
	def __init__(self, klassName, Format):
		if klassName.endswith('Subst'):
			Typ = 'Sub'
			Type = 'Subst'
		else:
			Typ = 'Pos'
			Type = 'Pos'
		if klassName.startswith('Chain'):
			Chain = 'Chain'
			InputIdx = 1
			DataLen = 3
		else:
			Chain = ''
			InputIdx = 0
			DataLen = 1
		ChainTyp = Chain+Typ

		self.Typ = Typ
		self.Type = Type
		self.Chain = Chain
		self.ChainTyp = ChainTyp
		self.InputIdx = InputIdx
		self.DataLen = DataLen

		self.LookupRecord = Type+'LookupRecord'

		if Format == 1:
			Coverage = lambda r: r.Coverage
			ChainCoverage = lambda r: r.Coverage
			ContextData = lambda r:(None,)
			ChainContextData = lambda r:(None, None, None)
			SetContextData = None
			SetChainContextData = None
			RuleData = lambda r:(r.Input,)
			ChainRuleData = lambda r:(r.Backtrack, r.Input, r.LookAhead)
			def SetRuleData(r, d):
				(r.Input,) = d
				(r.GlyphCount,) = (len(x)+1 for x in d)
			def ChainSetRuleData(r, d):
				(r.Backtrack, r.Input, r.LookAhead) = d
				(r.BacktrackGlyphCount,r.InputGlyphCount,r.LookAheadGlyphCount,) = (len(d[0]),len(d[1])+1,len(d[2]))
		elif Format == 2:
			Coverage = lambda r: r.Coverage
			ChainCoverage = lambda r: r.Coverage
			ContextData = lambda r:(r.ClassDef,)
			ChainContextData = lambda r:(r.BacktrackClassDef,
						     r.InputClassDef,
						     r.LookAheadClassDef)
			def SetContextData(r, d):
				(r.ClassDef,) = d
			def SetChainContextData(r, d):
				(r.BacktrackClassDef,
				 r.InputClassDef,
				 r.LookAheadClassDef) = d
			RuleData = lambda r:(r.Class,)
			ChainRuleData = lambda r:(r.Backtrack, r.Input, r.LookAhead)
			def SetRuleData(r, d):
				(r.Class,) = d
				(r.GlyphCount,) = (len(x)+1 for x in d)
			def ChainSetRuleData(r, d):
				(r.Backtrack, r.Input, r.LookAhead) = d
				(r.BacktrackGlyphCount,r.InputGlyphCount,r.LookAheadGlyphCount,) = (len(d[0]),len(d[1])+1,len(d[2]))
		elif Format == 3:
			Coverage = lambda r: r.Coverage[0]
			ChainCoverage = lambda r: r.InputCoverage[0]
			ContextData = None
			ChainContextData = None
			SetContextData = None
			SetChainContextData = None
			RuleData = lambda r: r.Coverage
			ChainRuleData = lambda r:(r.BacktrackCoverage +
						  r.InputCoverage +
						  r.LookAheadCoverage)
			def SetRuleData(r, d):
				(r.Coverage,) = d
				(r.GlyphCount,) = (len(x) for x in d)
			def ChainSetRuleData(r, d):
				(r.BacktrackCoverage, r.InputCoverage, r.LookAheadCoverage) = d
				(r.BacktrackGlyphCount,r.InputGlyphCount,r.LookAheadGlyphCount,) = (len(x) for x in d)
		else:
			assert 0, "unknown format: %s" % Format

		if Chain:
			self.Coverage = ChainCoverage
			self.ContextData = ChainContextData
			self.SetContextData = SetChainContextData
			self.RuleData = ChainRuleData
			self.SetRuleData = ChainSetRuleData
		else:
			self.Coverage = Coverage
			self.ContextData = ContextData
			self.SetContextData = SetContextData
			self.RuleData = RuleData
			self.SetRuleData = SetRuleData

		if Format == 1:
			self.Rule = ChainTyp+'Rule'
			self.RuleCount = ChainTyp+'RuleCount'
			self.RuleSet = ChainTyp+'RuleSet'
			self.RuleSetCount = ChainTyp+'RuleSetCount'
			self.Intersect = lambda glyphs, c, r: [r] if r in glyphs else []
		elif Format == 2:
			self.Rule = ChainTyp+'ClassRule'
			self.RuleCount = ChainTyp+'ClassRuleCount'
			self.RuleSet = ChainTyp+'ClassSet'
			self.RuleSetCount = ChainTyp+'ClassSetCount'
			self.Intersect = lambda glyphs, c, r: (c.intersect_class(glyphs, r) if c
							       else (set(glyphs) if r == 0 else set()))

			self.ClassDef = 'InputClassDef' if Chain else 'ClassDef'
			self.ClassDefIndex = 1 if Chain else 0
			self.Input = 'Input' if Chain else 'Class'

def parseLookupRecords(items, klassName, lookupMap=None):
	klass = getattr(ot, klassName)
	lst = []
	for item in items:
		rec = klass()
		item = stripSplitComma(item)
		assert len(item) == 2, item
		idx = int(item[0])
		assert idx > 0, idx
		rec.SequenceIndex = idx - 1
		setReference(mapLookup, lookupMap, item[1], setattr, rec, 'LookupListIndex')
		lst.append(rec)
	return lst

def makeClassDef(classDefs, font, klass=ot.Coverage):
	if not classDefs: return None
	self = klass()
	self.classDefs = dict(classDefs)
	return self

def parseClassDef(lines, font, klass=ot.ClassDef):
	classDefs = {}
	with lines.between('class definition'):
		for line in lines:
			glyph = makeGlyph(line[0])
			assert glyph not in classDefs, glyph
			classDefs[glyph] = int(line[1])
	return makeClassDef(classDefs, font, klass)

def makeCoverage(glyphs, font, klass=ot.Coverage):
	if not glyphs: return None
	if isinstance(glyphs, set):
		glyphs = sorted(glyphs)
	coverage = klass()
	coverage.glyphs = sorted(set(glyphs), key=font.getGlyphID)
	return coverage

def parseCoverage(lines, font, klass=ot.Coverage):
	glyphs = []
	with lines.between('coverage definition'):
		for line in lines:
			glyphs.append(makeGlyph(line[0]))
	return makeCoverage(glyphs, font, klass)

def bucketizeRules(self, c, rules, bucketKeys):
	buckets = {}
	for seq,recs in rules:
		buckets.setdefault(seq[c.InputIdx][0], []).append((tuple(s[1 if i==c.InputIdx else 0:] for i,s in enumerate(seq)), recs))

	rulesets = []
	for firstGlyph in bucketKeys:
		if firstGlyph not in buckets:
			rulesets.append(None)
			continue
		thisRules = []
		for seq,recs in buckets[firstGlyph]:
			rule = getattr(ot, c.Rule)()
			c.SetRuleData(rule, seq)
			setattr(rule, c.Type+'Count', len(recs))
			setattr(rule, c.LookupRecord, recs)
			thisRules.append(rule)

		ruleset = getattr(ot, c.RuleSet)()
		setattr(ruleset, c.Rule, thisRules)
		setattr(ruleset, c.RuleCount, len(thisRules))
		rulesets.append(ruleset)

	setattr(self, c.RuleSet, rulesets)
	setattr(self, c.RuleSetCount, len(rulesets))

def parseContext(lines, font, Type, lookupMap=None):
	self = getattr(ot, Type)()
	typ = lines.peeks()[0].split()[0].lower()
	if typ == 'glyph':
		self.Format = 1
		log.debug("Parsing %s format %s", Type, self.Format)
		c = ContextHelper(Type, self.Format)
		rules = []
		for line in lines:
			assert line[0].lower() == 'glyph', line[0]
			while len(line) < 1+c.DataLen: line.append('')
			seq = tuple(makeGlyphs(stripSplitComma(i)) for i in line[1:1+c.DataLen])
			recs = parseLookupRecords(line[1+c.DataLen:], c.LookupRecord, lookupMap)
			rules.append((seq, recs))

		firstGlyphs = set(seq[c.InputIdx][0] for seq,recs in rules)
		self.Coverage = makeCoverage(firstGlyphs, font)
		bucketizeRules(self, c, rules, self.Coverage.glyphs)
	elif typ.endswith('class'):
		self.Format = 2
		log.debug("Parsing %s format %s", Type, self.Format)
		c = ContextHelper(Type, self.Format)
		classDefs = [None] * c.DataLen
		while lines.peeks()[0].endswith("class definition begin"):
			typ = lines.peek()[0][:-len("class definition begin")].lower()
			idx,klass = {
			1: {
				'':		(0,ot.ClassDef),
			},
			3: {
				'backtrack':	(0,ot.BacktrackClassDef),
				'':		(1,ot.InputClassDef),
				'lookahead':	(2,ot.LookAheadClassDef),
			},
			}[c.DataLen][typ]
			assert classDefs[idx] is None, idx
			classDefs[idx] = parseClassDef(lines, font, klass=klass)
		c.SetContextData(self, classDefs)
		rules = []
		for line in lines:
			assert line[0].lower().startswith('class'), line[0]
			while len(line) < 1+c.DataLen: line.append('')
			seq = tuple(intSplitComma(i) for i in line[1:1+c.DataLen])
			recs = parseLookupRecords(line[1+c.DataLen:], c.LookupRecord, lookupMap)
			rules.append((seq, recs))
		firstClasses = set(seq[c.InputIdx][0] for seq,recs in rules)
		firstGlyphs = set(g for g,c in classDefs[c.InputIdx].classDefs.items() if c in firstClasses)
		self.Coverage = makeCoverage(firstGlyphs, font)
		bucketizeRules(self, c, rules, range(max(firstClasses) + 1))
	elif typ.endswith('coverage'):
		self.Format = 3
		log.debug("Parsing %s format %s", Type, self.Format)
		c = ContextHelper(Type, self.Format)
		coverages = tuple([] for i in range(c.DataLen))
		while lines.peeks()[0].endswith("coverage definition begin"):
			typ = lines.peek()[0][:-len("coverage definition begin")].lower()
			idx,klass = {
			1: {
				'':		(0,ot.Coverage),
			},
			3: {
				'backtrack':	(0,ot.BacktrackCoverage),
				'input':	(1,ot.InputCoverage),
				'lookahead':	(2,ot.LookAheadCoverage),
			},
			}[c.DataLen][typ]
			coverages[idx].append(parseCoverage(lines, font, klass=klass))
		c.SetRuleData(self, coverages)
		lines = list(lines)
		assert len(lines) == 1
		line = lines[0]
		assert line[0].lower() == 'coverage', line[0]
		recs = parseLookupRecords(line[1:], c.LookupRecord, lookupMap)
		setattr(self, c.Type+'Count', len(recs))
		setattr(self, c.LookupRecord, recs)
	else:
		assert 0, typ
	return self

def parseContextSubst(lines, font, lookupMap=None):
	return parseContext(lines, font, "ContextSubst", lookupMap=lookupMap)
def parseContextPos(lines, font, lookupMap=None):
	return parseContext(lines, font, "ContextPos", lookupMap=lookupMap)
def parseChainedSubst(lines, font, lookupMap=None):
	return parseContext(lines, font, "ChainContextSubst", lookupMap=lookupMap)
def parseChainedPos(lines, font, lookupMap=None):
	return parseContext(lines, font, "ChainContextPos", lookupMap=lookupMap)

def parseReverseChainedSubst(lines, font, _lookupMap=None):
	self = ot.ReverseChainSingleSubst()
	self.Format = 1
	coverages = ([], [])
	while lines.peeks()[0].endswith("coverage definition begin"):
		typ = lines.peek()[0][:-len("coverage definition begin")].lower()
		idx,klass = {
			'backtrack':	(0,ot.BacktrackCoverage),
			'lookahead':	(1,ot.LookAheadCoverage),
		}[typ]
		coverages[idx].append(parseCoverage(lines, font, klass=klass))
	self.BacktrackCoverage = coverages[0]
	self.BacktrackGlyphCount = len(self.BacktrackCoverage)
	self.LookAheadCoverage = coverages[1]
	self.LookAheadGlyphCount = len(self.LookAheadCoverage)
	mapping = {}
	for line in lines:
		assert len(line) == 2, line
		line = makeGlyphs(line)
		mapping[line[0]] = line[1]
	self.Coverage = makeCoverage(set(mapping.keys()), font)
	self.Substitute = [mapping[k] for k in self.Coverage.glyphs]
	self.GlyphCount = len(self.Substitute)
	return self

def parseLookup(lines, tableTag, font, lookupMap=None):
	line = lines.expect('lookup')
	_, name, typ = line
	log.debug("Parsing lookup type %s %s", typ, name)
	lookup = ot.Lookup()
	lookup.LookupFlag,filterset = parseLookupFlags(lines)
	if filterset is not None:
		lookup.MarkFilteringSet = filterset
	lookup.LookupType, parseLookupSubTable = {
		'GSUB': {
			'single':	(1,	parseSingleSubst),
			'multiple':	(2,	parseMultiple),
			'alternate':	(3,	parseAlternate),
			'ligature':	(4,	parseLigature),
			'context':	(5,	parseContextSubst),
			'chained':	(6,	parseChainedSubst),
			'reversechained':(8,	parseReverseChainedSubst),
		},
		'GPOS': {
			'single':	(1,	parseSinglePos),
			'pair':		(2,	parsePair),
			'kernset':	(2,	parseKernset),
			'cursive':	(3,	parseCursive),
			'mark to base':	(4,	parseMarkToBase),
			'mark to ligature':(5,	parseMarkToLigature),
			'mark to mark':	(6,	parseMarkToMark),
			'context':	(7,	parseContextPos),
			'chained':	(8,	parseChainedPos),
		},
	}[tableTag][typ]

	with lines.until('lookup end'):
		subtables = []

		while lines.peek():
			with lines.until(('% subtable', 'subtable end')):
				while lines.peek():
					subtable = parseLookupSubTable(lines, font, lookupMap)
					assert lookup.LookupType == subtable.LookupType
					subtables.append(subtable)
			if lines.peeks()[0] in ('% subtable', 'subtable end'):
				next(lines)
	lines.expect('lookup end')

	lookup.SubTable = subtables
	lookup.SubTableCount = len(lookup.SubTable)
	if lookup.SubTableCount is 0:
		# Remove this return when following is fixed:
		# https://github.com/fonttools/fonttools/issues/789
		return None
	return lookup

def parseGSUBGPOS(lines, font, tableTag):
	container = ttLib.getTableClass(tableTag)()
	lookupMap = DeferredMapping()
	featureMap = DeferredMapping()
	assert tableTag in ('GSUB', 'GPOS')
	log.debug("Parsing %s", tableTag)
	self = getattr(ot, tableTag)()
	self.Version = 0x00010000
	fields = {
		'script table begin':
		('ScriptList',
		 lambda lines: parseScriptList (lines, featureMap)),
		'feature table begin':
		('FeatureList',
		 lambda lines: parseFeatureList (lines, lookupMap, featureMap)),
		'lookup':
		('LookupList',
		 None),
	}
	for attr,parser in fields.values():
		setattr(self, attr, None)
	while lines.peek() is not None:
		typ = lines.peek()[0].lower()
		if typ not in fields:
			log.debug('Skipping %s', lines.peek())
			next(lines)
			continue
		attr,parser = fields[typ]
		if typ == 'lookup':
			if self.LookupList is None:
				self.LookupList = ot.LookupList()
				self.LookupList.Lookup = []
			_, name, _ = lines.peek()
			lookup = parseLookup(lines, tableTag, font, lookupMap)
			if lookupMap is not None:
				assert name not in lookupMap, "Duplicate lookup name: %s" % name
				lookupMap[name] = len(self.LookupList.Lookup)
			else:
				assert int(name) == len(self.LookupList.Lookup), "%d %d" % (name, len(self.Lookup))
			self.LookupList.Lookup.append(lookup)
		else:
			assert getattr(self, attr) is None, attr
			setattr(self, attr, parser(lines))
	if self.LookupList:
		self.LookupList.LookupCount = len(self.LookupList.Lookup)
	if lookupMap is not None:
		lookupMap.applyDeferredMappings()
	if featureMap is not None:
		featureMap.applyDeferredMappings()
	container.table = self
	return container

def parseGSUB(lines, font):
	return parseGSUBGPOS(lines, font, 'GSUB')
def parseGPOS(lines, font):
	return parseGSUBGPOS(lines, font, 'GPOS')

def parseAttachList(lines, font):
	points = {}
	with lines.between('attachment list'):
		for line in lines:
			glyph = makeGlyph(line[0])
			assert glyph not in points, glyph
			points[glyph] = [int(i) for i in line[1:]]
	return otl.buildAttachList(points, font.getReverseGlyphMap())

def parseCaretList(lines, font):
	carets = {}
	with lines.between('carets'):
		for line in lines:
			glyph = makeGlyph(line[0])
			assert glyph not in carets, glyph
			num = int(line[1])
			thisCarets = [int(i) for i in line[2:]]
			assert num == len(thisCarets), line
			carets[glyph] = thisCarets
	return otl.buildLigCaretList(carets, {}, font.getReverseGlyphMap())

def makeMarkFilteringSets(sets, font):
	self = ot.MarkGlyphSetsDef()
	self.MarkSetTableFormat = 1
	self.MarkSetCount = 1 + max(sets.keys())
	self.Coverage = [None] * self.MarkSetCount
	for k,v in sorted(sets.items()):
		self.Coverage[k] = makeCoverage(set(v), font)
	return self

def parseMarkFilteringSets(lines, font):
	sets = {}
	with lines.between('set definition'):
		for line in lines:
			assert len(line) == 2, line
			glyph = makeGlyph(line[0])
			# TODO accept set names
			st = int(line[1])
			if st not in sets:
				sets[st] = []
			sets[st].append(glyph)
	return makeMarkFilteringSets(sets, font)

def parseGDEF(lines, font):
	container = ttLib.getTableClass('GDEF')()
	log.debug("Parsing GDEF")
	self = ot.GDEF()
	fields = {
		'class definition begin':
			('GlyphClassDef',
			 lambda lines, font: parseClassDef(lines, font, klass=ot.GlyphClassDef)),
		'attachment list begin':
			('AttachList', parseAttachList),
		'carets begin':
			('LigCaretList', parseCaretList),
		'mark attachment class definition begin':
			('MarkAttachClassDef',
			 lambda lines, font: parseClassDef(lines, font, klass=ot.MarkAttachClassDef)),
		'markfilter set definition begin':
			('MarkGlyphSetsDef', parseMarkFilteringSets),
	}
	for attr,parser in fields.values():
		setattr(self, attr, None)
	while lines.peek() is not None:
		typ = lines.peek()[0].lower()
		if typ not in fields:
			log.debug('Skipping %s', typ)
			next(lines)
			continue
		attr,parser = fields[typ]
		assert getattr(self, attr) is None, attr
		setattr(self, attr, parser(lines, font))
	self.Version = 0x00010000 if self.MarkGlyphSetsDef is None else 0x00010002
	container.table = self
	return container

def parseCmap(lines, font):
	container = ttLib.getTableClass('cmap')()
	log.debug("Parsing cmap")
	tables = []
	while lines.peek() is not None:
		lines.expect('cmap subtable %d' % len(tables))
		platId, encId, fmt, lang = [
			parseCmapId(lines, field)
			for field in ('platformID', 'encodingID', 'format', 'language')]
		table = cmap_classes[fmt](fmt)
		table.platformID = platId
		table.platEncID = encId
		table.language = lang
		table.cmap = {}
		line = next(lines)
		while line[0] != 'end subtable':
			table.cmap[int(line[0], 16)] = line[1]
			line = next(lines)
		tables.append(table)
	container.tableVersion = 0
	container.tables = tables
	return container

def parseCmapId(lines, field):
	line = next(lines)
	assert field == line[0]
	return int(line[1])

def parseTable(lines, font, tableTag=None):
	log.debug("Parsing table")
	line = lines.peeks()
	tag = None
	if line[0].split()[0] == 'FontDame':
		tag = line[0].split()[1]
	elif ' '.join(line[0].split()[:3]) == 'Font Chef Table':
		tag = line[0].split()[3]
	if tag is not None:
		next(lines)
		tag = tag.ljust(4)
		if tableTag is None:
			tableTag = tag
		else:
			assert tableTag == tag, (tableTag, tag)

	assert tableTag is not None, "Don't know what table to parse and data doesn't specify"

	return {
		'GSUB': parseGSUB,
		'GPOS': parseGPOS,
		'GDEF': parseGDEF,
		'cmap': parseCmap,
		}[tableTag](lines, font)

class Tokenizer(object):

	def __init__(self, f):
		# TODO BytesIO / StringIO as needed?  also, figure out whether we work on bytes or unicode
		lines = iter(f)
		try:
			self.filename = f.name
		except:
			self.filename = None
		self.lines = iter(lines)
		self.line = ''
		self.lineno = 0
		self.stoppers = []
		self.buffer = None

	def __iter__(self):
		return self

	def _next_line(self):
		self.lineno += 1
		line = self.line = next(self.lines)
		line = [s.strip() for s in line.split('\t')]
		if len(line) == 1 and not line[0]:
			del line[0]
		if line and not line[-1]:
			log.warning('trailing tab found on line %d: %s' % (self.lineno, self.line))
			while line and not line[-1]:
				del line[-1]
		return line

	def _next_nonempty(self):
		while True:
			line = self._next_line()
			# Skip comments and empty lines
			if line and line[0] and (line[0][0] != '%' or line[0] == '% subtable'):
				return line

	def _next_buffered(self):
		if self.buffer:
			ret = self.buffer
			self.buffer = None
			return ret
		else:
			return self._next_nonempty()

	def __next__(self):
		line = self._next_buffered()
		if line[0].lower() in self.stoppers:
			self.buffer = line
			raise StopIteration
		return line

	def next(self):
		return self.__next__()

	def peek(self):
		if not self.buffer:
			try:
				self.buffer = self._next_nonempty()
			except StopIteration:
				return None
		if self.buffer[0].lower() in self.stoppers:
			return None
		return self.buffer

	def peeks(self):
		ret = self.peek()
		return ret if ret is not None else ('',)

	@contextmanager
	def between(self, tag):
		start = tag + ' begin'
		end = tag + ' end'
		self.expectendswith(start)
		self.stoppers.append(end)
		yield
		del self.stoppers[-1]
		self.expect(tag + ' end')

	@contextmanager
	def until(self, tags):
		if type(tags) is not tuple:
			tags = (tags,)
		self.stoppers.extend(tags)
		yield
		del self.stoppers[-len(tags):]

	def expect(self, s):
		line = next(self)
		tag = line[0].lower()
		assert tag == s, "Expected '%s', got '%s'" % (s, tag)
		return line

	def expectendswith(self, s):
		line = next(self)
		tag = line[0].lower()
		assert tag.endswith(s), "Expected '*%s', got '%s'" % (s, tag)
		return line

def build(f, font, tableTag=None):
	lines = Tokenizer(f)
	return parseTable(lines, font, tableTag=tableTag)


def main(args=None, font=None):
	import sys
	from fontTools import configLogger
	from fontTools.misc.testTools import MockFont

	if args is None:
		args = sys.argv[1:]

	# configure the library logger (for >= WARNING)
	configLogger()
	# comment this out to enable debug messages from mtiLib's logger
	# log.setLevel(logging.DEBUG)

	if font is None:
		font = MockFont()

	tableTag = None
	if args[0].startswith('-t'):
		tableTag = args[0][2:]
		del args[0]
	for f in args:
		log.debug("Processing %s", f)
		table = build(open(f, 'rt', encoding="utf-8"), font, tableTag=tableTag)
		blob = table.compile(font) # Make sure it compiles
		decompiled = table.__class__()
		decompiled.decompile(blob, font) # Make sure it decompiles!

		#continue
		from fontTools.misc import xmlWriter
		tag = table.tableTag
		writer = xmlWriter.XMLWriter(sys.stdout)
		writer.begintag(tag)
		writer.newline()
		#table.toXML(writer, font)
		decompiled.toXML(writer, font)
		writer.endtag(tag)
		writer.newline()


if __name__ == '__main__':
	import sys
	sys.exit(main())
