"""
     qtgui/FontedPositionedStrings.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2010 University of York

     This library is free software: you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public License
     version 3, modified in accordance with the provisions of the 
     license to address the requirements of UK law.
 
     You should have received a copy of the modified GNU Lesser General 
     Public License along with this library.  If not, copies may be 
     downloaded from http://www.ccp4.ac.uk/ccp4license.php
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser General Public License for more details.
"""
from PyQt4 import QtCore,QtGui
import ParseHTMLTextString
import sys

def drawFontedPositionedStrings(strings,painter,xorig=0,yorig=0,defaultFont=None):
		"""
		This function needs implementing in C++ also, wherein the strings
		will have to be more managable objects.
		"""
		if not defaultFont: defaultFont = QtGui.QFont("Times",12)
		defaultPenColor = painter.pen().color()
		for s,i in zip(strings[:],range(len(strings))):
			if s["font"]["face"]=="default":
				font = QtGui.QFont(defaultFont)
			 	if s["font"]["fontUnits"] == "px":
					font.setPixelSize(int(s["font"]["size"]))
				else:
					font.setPointSize(int(s["font"]["size"]))
			else:
				font = QtGui.QFont(s["font"]["face"])
				if s["font"]["fontUnits"] == "px":
					font.setPixelSize(int(s["font"]["size"]))
				else:
					font.setPointSize(int(s["font"]["size"]))
				font.setBold(int(s["font"]["bold"]))
				font.setItalic(int(s["font"]["italic"]))
				font.setUnderline(int(s["font"]["underline"]))
				font.setOverline(int(s["font"]["overline"]))
				font.setStrikeOut(int(s["font"]["linethrough"]))

			if s["font"]["colour"] == "default":
				painter.setPen(defaultPenColor)
			else:
				col = QtGui.QColor(s["font"]["colour"])
				if s["font"].has_key("alpha"):
					col.setAlpha(int(s["font"]["alpha"]))
				painter.setPen(col)
			painter.setFont(font)
			x,y = s["pos"]
			text = s["text"]
	
			"""
			print type(text),text
			codec = QtCore.QTextCodec.codecForName("ISO 8859-1")
			text = QtCore.QString(codec.fromUnicode(text))
			print type(text)
			"""

			painter.drawText(x+xorig,y+yorig,text);
		painter.setFont(defaultFont)

class FontedPositionedStringsFromText:
	def getBoundingRect(self):
		return self.fonted_strings.getBoundingRect()

	def getDescent(self):
		return self.fonted_strings.getDescent()

	def getStrings(self):
		return self.fonted_strings.getStrings()

	def __init__(self,text,defaultFont=None,fontScaling=1.0):
		if not defaultFont: defaultFont = QtGui.QFont("Times",12)
		if defaultFont.pointSize()>0:
	        	parser = ParseHTMLTextString.MyHTMLParser(int(defaultFont.pointSize()*fontScaling))
		else:
	        	parser = ParseHTMLTextString.MyHTMLParser(int(defaultFont.pixelSize()*fontScaling),"px")
		parser.feed(text)
		self.fontedStrings = parser.getStrings()
		self.fontedStringsLength = parser.getDataLength()
		self.fonted_strings = FontedPositionedStrings(self.fontedStrings,defaultFont,fontScaling)

class FontedPositionedStrings:
	def getStrings(self):
		return self.strings

	def getDescent(self):
		return self.descent

	def getBoundingRect(self):
		return self.boundingRect

	def __init__(self,strings,defaultFont=None,fontScaling=1.0):
		currentParagraph = 0
		x = 0
		y = 0
		self.descent = 0
		baseline_y = 0
		old_baseline_y = 0
		max_x = 0
		max_y = 0
		min_x = 0
		min_y = 0
		currentSubLevel = 0
		currentSupLevel = 0
		lastSubLevel = currentSubLevel
		lastSupLevel = currentSupLevel

		previousStartSup = False 
		previousStartSub = False 
		previousEndSup = False
		previousEndSub = False
		justDoneSup = False
		justDoneSub = False
		branchDepth = 0
		branches = [[0,0]]
		branch_start_x,branch_end_x = 0,0
		doMathMarkup = False

		fontedPositionedStrings = []
		if not defaultFont: defaultFont = QtGui.QFont("Times",int(12*fontScaling))
		"""
		for s in strings[:]:
			print '----'+s["text"]+'----'
		"""
                # s["font"] really means proprties of a chunk of data, s["text"] is the text in that chunk.
		for s in strings[:]:
			if s["font"]["face"]=="default":
				font = QtGui.QFont(defaultFont)
			 	if s["font"]["fontUnits"] == "px":
					font.setPixelSize(int(s["font"]["size"]))
				else:
					font.setPointSize(int(s["font"]["size"]))
			else:
				font = QtGui.QFont(s["font"]["face"])
			 	if s["font"]["fontUnits"] == "px":
					font.setPixelSize(int(s["font"]["size"]*fontScaling))
				else:
					font.setPointSize(int(s["font"]["size"]*fontScaling))
				font.setBold(int(s["font"]["bold"]))
				font.setItalic(int(s["font"]["italic"]))
				font.setUnderline(int(s["font"]["underline"]))
				font.setOverline(int(s["font"]["overline"]))
				font.setStrikeOut(int(s["font"]["linethrough"]))

			#print s["font"]["paragraph"],s["text"]

			if s["font"]["fontUnits"] == "px":
				desiredSize = font.pixelSize()
			else:
				desiredSize = font.pointSize()
			change = False
			startSup = False
			startSub = False
			endSup = False
			endSub = False
			doMathMarkup = s["font"]["mathmarkup"]
			#print "1: ",desiredSize
			if int(s["font"]["superscript"]) > currentSupLevel:
				currentSupLevel = currentSupLevel+1
				desiredSize = max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9)
				y = (y - 0.7*desiredSize)
				change = True
				startSup = True
			#print "2: ",desiredSize
			if int(s["font"]["superscript"]) < currentSupLevel:
				y = (y + 0.7*max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9))
				currentSupLevel = max(currentSupLevel-1,0)
				desiredSize = max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9)
				change = True
				endSup = True

			#print "3: ",desiredSize
			if int(s["font"]["subscript"]) > currentSubLevel:
				currentSubLevel = currentSubLevel+1
				desiredSize = max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9)
				y = (y + 0.3*desiredSize)
				change = True
				startSub = True
			#print "4: ",desiredSize
			if int(s["font"]["subscript"]) < currentSubLevel:
				y = (y - 0.3*max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9))
				currentSubLevel = max(currentSubLevel-1,0)
				desiredSize = max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9)
				change = True
				endSub = True

                        """
			print endSub , startSup , endSup , startSub
                        """
			#print "5: ",desiredSize
			if not change: desiredSize = max(desiredSize*0.7**(currentSubLevel+currentSupLevel),9)

			if s["font"]["paragraph"]>currentParagraph:
				currentParagraph = currentParagraph + 1
				old_baseline_y = baseline_y
				baseline_y = baseline_y+QtGui.QFontMetrics(font).height()
				x = 0
			else:
				if old_baseline_y+QtGui.QFontMetrics(font).height()>baseline_y and currentParagraph>0:
					#print "Font has gotten bigger",old_baseline_y+QtGui.QFontMetrics(font).height(),baseline_y
					for sold in strings[:]:
						if sold["font"]["paragraph"]==currentParagraph and sold is not s and sold.has_key("pos"):
							xold,yold = sold["pos"]
							yold = yold + old_baseline_y+QtGui.QFontMetrics(font).height()-baseline_y
							sold["pos"] = (xold,yold)
					
					baseline_y = old_baseline_y+QtGui.QFontMetrics(font).height()
			if int(s["font"]["valign"])==0:
				ydraw = baseline_y
			elif int(s["font"]["valign"])==1:
				ydraw = baseline_y+desiredSize*0.3
				desiredSize = max(desiredSize*0.7,9)
			elif int(s["font"]["valign"])==2:
				ydraw = baseline_y-desiredSize*0.5
				desiredSize = max(desiredSize*0.7,9)
			else:
				ydraw = baseline_y+y

			#print "6: ",desiredSize
			if s["font"]["fontUnits"] == "px":
				font.setPixelSize(int(desiredSize))
			else:
				font.setPointSize(int(desiredSize))
			fm = QtGui.QFontMetrics(font)

			if startSub or startSup:
				#print startSup, justDoneSub, justDoneSup, startSub,s["text"]
				#if s["text"] == "fg" or s["text"] == "jkl" or s["text"] == "abc":
				if doMathMarkup and ((startSub and justDoneSup) or (startSup and justDoneSub)):
					x = branch_start_x
					#print "yes ..."
				branchDepth = branchDepth + 1
				branches.append([x,max(x,branch_end_x)])
			if endSub or endSup:
				branchDepth = branchDepth - 1
				branch_start_x,branch_end_x = branches.pop()
				x = branch_end_x
			if endSup:
				justDoneSup = True
			if endSub:
				justDoneSub = True

			s["pos"] = (x,int(ydraw))
			s["font"]["size"] = int(desiredSize)
			fontedPositionedStrings.append(s)

			rect = fm.boundingRect(s["text"])
			self.descent = max(fm.descent(),self.descent)
			#print (rect.left(),rect.right()), (rect.top(),rect.bottom()), (x,y), (min_x,min_y)

			if x>max_x: max_x = x
			if ydraw>max_y: max_y = ydraw
			if x<min_x: min_x = x
			if ydraw<min_y: min_y = ydraw
			if x+rect.left()<min_x: min_x = x+rect.left()
			if x+rect.right()>max_x: max_x = x+rect.right()
			if ydraw+rect.top()<min_y: min_y = ydraw+rect.top()
			if ydraw+rect.bottom()>max_y: max_y = ydraw+rect.bottom()
			# It could go either way
			if x+rect.left()>max_x: max_x = x+rect.left()
			if x+rect.right()<min_x: min_x = x+rect.right()
			if ydraw+rect.top()>max_y: max_y = ydraw+rect.top()
			if ydraw+rect.bottom()<min_y: min_y = ydraw+rect.bottom()
		  	x = x + fm.width(s["text"])
			branches[branchDepth][1] = max(x,branches[branchDepth][1])

			if len(s["text"])>0:
				justDoneSup = False
				justDoneSub = False

		#print branches,branchDepth
		bwidth = max_x-min_x+1
		bheight = max_y-min_y+1
		bx = min_x
		by = min_y
		self.boundingRect = QtCore.QRect(bx,by,bwidth,bheight)
		self.strings = fontedPositionedStrings
		if len(self.strings)>1:
			ymax = self.strings[-1]['pos'][1]
			for sss in self.strings:
				sss['pos'] = (sss['pos'][0],(sss['pos'][1])-ymax)
