#!/usr/bin/env python

import pygtk
import time
pygtk.require("2.0")
import gtk
import cairo
import symbols
import pdf_tounicodes
from matrices import default_font_matrix
from matrices import Matrix
from matrices import make_vector
from matrices import make_translation_matrix
from matrices import I

class PageRenderer(object):
	def __init__(self, widget):
		self.T_m = I.clone()
		self.T_lm = I.clone()
		self.font_matrix = default_font_matrix
		self.character_spacing = 0.0
		self.word_spacing = 0.0
		self.horizontal_text_scaling = 1.0
		self.horizontal_scaling = 1.0
		self.text_rise = 0.0
		self.widget = widget
		self.context = widget.window.cairo_create()
		self.text_leading = 0
		#self.context.stroke()
		self.things = []
	def add_image(self, buf):
		X = self.X # FIXME
		Y = self.Y
		loader = gtk.gdk.PixbufLoader()
		loader.write(buf, len(buf))
		loader.close()
		pixbuf = loader.get_pixbuf()
		self.things.append((X, Y, pixbuf, None))
		self.X = X
		self.Y = Y
	def add_text(self, texts, extra_data):
		UserUnit = self.UserUnit
		t_y = 0
		font, font_size = extra_data
		for item in texts:
			if isinstance(item, int): # distance.
				#self.advance(-font_size * item * self.horizontal_text_scaling / 1000, 0) # TODO make this more exact.
				t_x = (0 - item/1000.0) * font_size # + self.character_spacing # FIXME +self.word_spacing
				#X += 8 * width / 500
				self.T_m = make_translation_matrix(t_x, t_y) * self.T_m
				assert(self.T_m[2][1] >= 0) # FIXME remove
			else: # text
				values = pdf_tounicodes.get_values_for_characters(font.ToUnicode, item, lambda code: (font.get_char_width(code), font.get_char_glyph(code)))
				if font.ToUnicode:
					#print("TXTQQQ", item)
					pass # print("VALUES", values)
				# 
				print("M", self.T_m.transpose())
				print("V", make_vector(0, 0, 1))
				new_pos = self.font_matrix.transpose() * self.T_m.transpose() * make_vector(0, 0, 1)
				#new_pos2 = self.T_m.transpose() * make_vector(0, 0, 1) # old-style.
				X = new_pos[0][0] * 720 * UserUnit # FIXME 
				Y = new_pos[1][0] * 720 * UserUnit # FIXME
				print("P", X, Y) # , new_pos2[0][0] / 1000.0, new_pos2[1][0] / 1000.0)
				self.things.append((X, Y, u"".join([x[0] for x in values]), extra_data))
				for x in values:
					width = x[1][0]
					glyph = x[1][1]
					print("glyph", glyph)
					print("width", x[1])
					t_x = width * font_size + self.character_spacing # FIXME +self.word_spacing
					#X += 8 * width / 500
					self.T_m = make_translation_matrix(t_x, t_y) * self.T_m
					assert(self.T_m[2][1] >= 0) # FIXME remove
				#X += 8 * len(values)
				if X >= 800:
					X = 0
					Y += 8
	def set_user_unit(self, value):
		self.UserUnit = value # in 1/72 of an inch.
	def advance(self, dX, dY):
		if dY != 0:
			print(self.T_m)
		self.T_m = make_translation_matrix(dX, dY) * self.T_m
		assert(self.T_m[2][1] >= 0) # FIXME remove
		if dY != 0:
			print("=>", self.T_m)
		#self.X += dX
	def add_operation(self, operator_, operands, extra_data = None):
		print(operator_, operands)
		if operator_ == symbols.Do:
			self.add_image(extra_data)
		elif operator_ == symbols.Tstar:
			self.advance(0, -self.text_leading)
			pass
		elif operator_ == symbols.BT:
			pass # TODO Tm=I, Tlm=I
		elif operator_ == symbols.Ts: # text rise, unscaled, not cumulative.
			self.text_rise = operands[0]
		elif operator_ == symbols.Tc: # DO NOT special-handle font size
			self.character_spacing = operands[0]
		elif operator_ == symbols.TL:
			self.text_leading = operands[0]
		elif operator_ == symbols.Tw: # DO NOT special-handle font size
			# "word" space, that is, how big is a space character?
			self.word_spacing = operands[0]
			pass # TODO
		elif operator_ == symbols.Th: # horizontal scaling???
			self.horizontal_scaling = operands[0] / 100.0
		elif operator_ == symbols.Tz: # horizontal text scaling.
			self.horizontal_text_scaling = operands[0] / 100.0
		elif operator_ == symbols.Td:
			self.T_lm = self.T_m = make_translation_matrix(*operands) * self.T_lm # T_lm is the start of the current line!
			assert(self.T_m[2][1] >= 0) # FIXME remove
			print("Td", operands)
			self.advance(*operands)
		elif operator_ == symbols.Tm:
			a,b,c,d,e,f = operands
			self.T_lm = self.T_m = Matrix([[a, b, 0],
			                               [c, d, 0],
			                               [e, f, 1]])
			print("Tm")
			# T_m = T_lm = operands whereas:
			""" [[a b 0]
			     [c d 0]
			     [e f 1]] """
		elif operator_ == symbols.TJ or operator_ == symbols.Tj:
			if(operator_ == symbols.Tj):
				operator_ = symbols.TJ
				operands = [operands[0]]
			self.add_text(operands, extra_data)
	def render(self, widget, event):
		self.context = self.widget.window.cairo_create()
		#self.context.scale(0.7, 0.7)
		for X, Y, thing, extra in self.things:
			if isinstance(thing, gtk.gdk.Pixbuf):
				pixbuf = thing
				self.context.set_operator(cairo.OPERATOR_SOURCE)
				self.context.set_source_pixbuf(pixbuf, 0, 0)
				#self.context.scale(5, 5)
				self.context.paint()
				self.context.stroke()
				#self.context.set_source_rgb(0.5, 0.5, 0.5)
				#self.context.rectangle(0, 0, 100, 100)
				#self.context.fill()
			elif isinstance(thing, unicode):
				#print(thing)
				self.context.move_to(X, Y)
				# TODO set font extra[0]
				self.context.set_font_size(extra[1] * 0.5)
				self.context.show_text(thing)

"""
def someView(request):
  surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
  context = cairo.Context(surface)
  # Draw something ...

  response = HttpResponse(mimetype="image/png")
  surface.write_to_png(response)
  return response
"""

def create_default_window():
	window = gtk.Window()
	drawing_area = gtk.DrawingArea()
	window.add(drawing_area)
	#text_view = gtk.TextView()
	#window.add(text_view)
	window.show()
	drawing_area.show()
	window.realize()
	drawing_area.set_size_request(800, 600)
	drawing_area.realize()
	renderer = PageRenderer(drawing_area)
	return(window, drawing_area, renderer)

if __name__ == "__main__":
	window, renderer = create_default_window()
	window.connect("delete-event", gtk.main_quit)
	gtk.main()
