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

"""GUI font inspector.
"""

from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools import misc, ttLib, cffLib
import pygtk
pygtk.require('2.0')
import gtk
import sys



class Row(object):
	def __init__(self, parent, index, key, value, font):
		self._parent = parent
		self._index = index
		self._key = key
		self._value = value
		self._font = font

		if isinstance(value, ttLib.TTFont):
			self._add_font(value)
			return

		if not isinstance(value, basestring):
			# Try sequences
			is_sequence = True
			try:
				len(value)
				iter(value)
				# It's hard to differentiate list-type sequences
				# from dict-type ones.  Try fetching item 0.
				value[0]
			except (TypeError, AttributeError, KeyError, IndexError):
				is_sequence = False
			if is_sequence:
				self._add_list(key, value)
				return
		if hasattr(value, '__dict__'):
			self._add_object(key, value)
			return
		if hasattr(value, 'items'):
			self._add_dict(key, value)
			return

		if isinstance(value, basestring):
			self._value_str = '"'+value+'"'
			self._children = []
			return

		# Everything else
		self._children = []

	def _filter_items(self):
		items = []
		for k,v in self._items:
			if isinstance(v, ttLib.TTFont):
				continue
			if k in ['reader', 'file', 'tableTag', 'compileStatus', 'recurse']:
				continue
			if isinstance(k, basestring) and k[0] == '_':
				continue
			items.append((k,v))
		self._items = items

	def _add_font(self, font):
		self._items = [(tag,font[tag]) for tag in font.keys()]

	def _add_object(self, key, value):
		# Make sure item is decompiled
		try:
			value["asdf"]
		except (AttributeError, KeyError, TypeError, ttLib.TTLibError):
			pass
		if isinstance(value, ttLib.getTableModule('glyf').Glyph):
			# Glyph type needs explicit expanding to be useful
			value.expand(self._font['glyf'])
		if isinstance(value, misc.psCharStrings.T2CharString):
			try:
				value.decompile()
			except TypeError:  # Subroutines can't be decompiled
				pass
		if isinstance(value, cffLib.BaseDict):
			for k in value.rawDict.keys():
				getattr(value, k)
		if isinstance(value, cffLib.Index):
			# Load all items
			for i in range(len(value)):
				value[i]
			# Discard offsets as should not be needed anymore
			if hasattr(value, 'offsets'):
				del value.offsets

		self._value_str = value.__class__.__name__
		if isinstance(value, ttLib.tables.DefaultTable.DefaultTable):
			self._value_str += ' (%d Bytes)' % self._font.reader.tables[key].length
		self._items = sorted(value.__dict__.items())
		self._filter_items()

	def _add_dict(self, key, value):
		self._value_str = '%s of %d items' % (value.__class__.__name__, len(value))
		self._items = sorted(value.items())

	def _add_list(self, key, value):
		if len(value) and len(value) <= 32:
			self._value_str = str(value)
		else:
			self._value_str = '%s of %d items' % (value.__class__.__name__,
							      len(value))
		self._items = list(enumerate(value))

	def __len__(self):
		if hasattr(self, '_children'):
			return len(self._children)
		if hasattr(self, '_items'):
			return len(self._items)
		assert False

	def _ensure_children(self):
		if hasattr(self, '_children'):
			return
		children = []
		for i,(k,v) in enumerate(self._items):
			children.append(Row(self, i, k, v, self._font))
		self._children = children
		del self._items

	def __getitem__(self, n):
		if n >= len(self):
			return None
		if not hasattr(self, '_children'):
			self._children = [None] * len(self)
		c = self._children[n]
		if c is None:
			k,v = self._items[n]
			c = self._children[n] = Row(self, n, k, v, self._font)
			self._items[n] = None
		return c

	def get_parent(self):
		return self._parent

	def get_index(self):
		return self._index

	def get_key(self):
		return self._key

	def get_value(self):
		return self._value

	def get_value_str(self):
		if hasattr(self,'_value_str'):
			return self._value_str
		return str(self._value)

class FontTreeModel(gtk.GenericTreeModel):

	__gtype_name__ = 'FontTreeModel'

	def __init__(self, font):
		super(FontTreeModel, self).__init__()
		self._columns = (str, str)
		self.font = font
		self._root = Row(None, 0, "font", font, font)

	def on_get_flags(self):
		return 0

	def on_get_n_columns(self):
		return len(self._columns)

	def on_get_column_type(self, index):
		return self._columns[index]

	def on_get_iter(self, path):
		rowref = self._root
		while path:
			rowref = rowref[path[0]]
			path = path[1:]
		return rowref

	def on_get_path(self, rowref):
		path = []
		while rowref != self._root:
			path.append(rowref.get_index())
			rowref = rowref.get_parent()
		path.reverse()
		return tuple(path)

	def on_get_value(self, rowref, column):
		if column == 0:
			return rowref.get_key()
		else:
			return rowref.get_value_str()

	def on_iter_next(self, rowref):
		return rowref.get_parent()[rowref.get_index() + 1]

	def on_iter_children(self, rowref):
		return rowref[0]

	def on_iter_has_child(self, rowref):
		return bool(len(rowref))

	def on_iter_n_children(self, rowref):
		return len(rowref)

	def on_iter_nth_child(self, rowref, n):
		if not rowref: rowref = self._root
		return rowref[n]

	def on_iter_parent(self, rowref):
		return rowref.get_parent()

class Inspect(object):

	def _delete_event(self, widget, event, data=None):
		gtk.main_quit()
		return False

	def __init__(self, fontfile):

		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_title("%s - pyftinspect" % fontfile)
		self.window.connect("delete_event", self._delete_event)
		self.window.set_size_request(400, 600)

		self.scrolled_window = gtk.ScrolledWindow()
		self.window.add(self.scrolled_window)

		self.font = ttLib.TTFont(fontfile, lazy=True)
		self.treemodel = FontTreeModel(self.font)
		self.treeview = gtk.TreeView(self.treemodel)
		#self.treeview.set_reorderable(True)

		for i in range(2):
			col_name = ('Key', 'Value')[i]
			col = gtk.TreeViewColumn(col_name)
			col.set_sort_column_id(-1)
			self.treeview.append_column(col)

			cell = gtk.CellRendererText()
			col.pack_start(cell, True)
			col.add_attribute(cell, 'text', i)

		self.treeview.set_search_column(1)
		self.scrolled_window.add(self.treeview)
		self.window.show_all()

def main(args):
	if len(args) < 1:
		print("usage: pyftinspect font...", file=sys.stderr)
		sys.exit(1)
	for arg in args:
		Inspect(arg)
	gtk.main()

if __name__ == "__main__":
	main(sys.argv[1:])
