# Copyright 2006 Mounir Errami. m.errami@gmail.com
# This file is part of Bibus, a bibliographic database that can
# work together with OpenOffice.org to generate bibliographic indexes.
#
# Bibus is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Bibus 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bibus; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import win32com.client
import win32com.gen_py
from pywintypes import IID
import mswCONST
import mswFormatter
import mswUtils

#Example: for the Field Interface: see http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.word.field_members.aspx
class mswRef:
	"""This class uses Field interface from msWord. It contains stuff to create a ref and interact with it"""
	def __init__(self, mswapp, msField=None, data=None, result=None, code = None):
		if msField != None:
			self._Field = msField
			self.mswapp = mswapp #mswapp represent an instance of microsoft word
			self.mswFormatter = self.mswapp.getMSWFormatter()
		else:
			#Exception : mswapp has to be not null!
			self.mswapp = mswapp
			self.mswFormatter = self.mswapp.getMSWFormatter()
			try:
				rangeToField = mswapp.getMSWApplication().Selection.Range
				self._Field= mswapp.getMSWApplication().ActiveDocument.Fields.Add(rangeToField, mswCONST.me_wdFieldEmpty,"insert test",0)
				#Note: we can't use setCode and setData because msword won't accept it
				#We have to initialize the field directly before so that msword will unlock the field (it is the only way to screw msword)
				self._Field.Code.Text= code
				self._Field.Data = data
				#now setResult works, since msword has been forced to unlocked the field
				self.setResult(result)
				self.mswFormatter.normalizeCitationRangeFont(self._Field.Result)
				#if autoUpdate
				self.setCitationImmediateFormat()
				
			except AttributeError:
				pass

			
	
	
		
	def setResult(self,displayToUser): 
		"""result is the part of the field displayed to the user"""
		self._Field.Result.Text = displayToUser
		
	
	def setCode(self,code):
		"""Field.Code.Text is not display in the msword document
		If the users enters ALT+F9 in msword, the data will show up """

		if mswUtils.isFieldBiblio(self._Field)==False and  mswUtils.isFieldCitation(self._Field)==False:
			return False
		else:
			self._Field.Code.Text=code
			return True
	
	def setData(self,data):
		"""Enter code to change the Field.Data. No way to access this via word.
		this is a programming field, where to put some data and is not accessible from msword (for safety)"""
		if mswUtils.isFieldBiblio(self._Field)==False and  mswUtils.isFieldCitation(self._Field)==False:
			return False
		else:
			self._Field.Data = data
			return True
			
	def getMSWField(self):
		"""returns the Field object, as defined in word Field Interface"""
		return self._Field

	def getFieldValue(self,key):
		"""Returns a value from XML key in Field.Code.Text
		Example: <Author>Mounir Errami</Author>
		The function getFieldValue(aField, "Author") returns "Mounir Errami"
		print "looking for=", key, "for field:", field.Result.Text"""
		if mswUtils.isFieldCitation() == False:
			return None
		stringToParse = self._Field.Code.Text
		start = stringToParse.find("<"+key+">")
		if start ==-1:
			return None
		start = start + len(key)+2
		end = stringToParse.find("</"+key+">")
		if end ==-1:
			return None
		retString = stringToParse[start:end]
		return retString

	def getFieldKeys(self):
		"""Returns a list of all the XML style keys from a field"""
		if mswUtils.isFieldCitation(self._Fields) == False:
			return None
		mySplit=self._Field.Code.Text.split("<")
		keys=[]
		for myWord in mySplit:
			if myWord[0]=='/' and myWord[len(myWord)-1]=='>':
				newWord = myWord[1:len(myWord)-1]
				keys.append(newWord)
				#print "newWord =>%s<"%newWord
		#for key in keys:
			#print "key =>%s<"%key
		return keys
	
	def createCitationText(self):
		"""Create the text in citation according to user style
		it also updates all the citations for renumbering. Word doesn't do it automatically
		with the addin field.
		"""
		refId = self.getFieldValue("Identifier")
		citationIndex = 1
		oBrackets,cBrakets = self.mswFormatter.getBracket()
		if self.mswFormatter.isNumberEntries()==True :#and self.mswFormatter.isSortByPosition() == True :
			refIds = []
			Fields = self.mswapp.getMSWApplication().ActiveDocument.Fields
			for myField in Fields:
				nfo = mswRef(self.mswapp,myField)
				if mswUtils.isFieldCitation(myField)==False:
					continue
				idToComp = nfo.getFieldValue("Identifier")
				if refIds.count(idToComp)==0:
					refIds.append(idToComp)
				nfo.setResult(oBrackets+str(refIds.index(idToComp)+1)+cBrakets)
			
	def setCitationImmediateFormat(self):
		"""Set the format immediately when citation inserted"""
		resToChange = self._Field.Result
		resToChange.Select
		if self.mswFormatter.isNumberEntries():
			myFont = resToChange.Font
			#Citation position
			myFont.Superscript=self.mswFormatter.isCitationSuperscript()
			myFont.Subscript=self.mswFormatter.isCitationSubscript()
			#Citation character style
			#styledic would be = {'underline':False,'smallcaps':False,'caps':False,'bold':False,'italic':False,'regular':True}
			styleDic = self.mswFormatter.getCitationStyleDic()
			myFont.Bold=styleDic['bold']
			myFont.Italic=styleDic['italic']
			myFont.Underline=styleDic['underline']
			myFont.SmallCaps=styleDic['smallcaps']
			myFont.AllCaps=styleDic['caps']
			myFont.Bold=styleDic['bold']
		else:
			oBrackets,cBrakets = self.mswFormatter.getBracket()
			idToCite,newCiteText= self.mswFormatter.applyCitationTemplate(self._Field)
			self._Field.Result.Text = oBrackets+idToCite+cBrakets
			self._Field.Code.Text = newCiteText #if modify Code before changing Result, miscrosoft word bugs and won't accept the changes!
			self._Field.Data = mswCONST.me_MSWBIBUS_CITE_TAG #if modify Code before changing Result, miscrosoft word bugs and won't accept the changes!
			rangeString = mswUtils.getXmlValueFromString(mswCONST.me_MSWBIBUS_CITE_RANGES,newCiteText)
			thisRangeStart = self._Field.Result.Start
			firstStart = self._Field.Result.Start
			lastStop = self._Field.Result.End
			#print "rangeString=",rangeString
			rangeList = []
			myRangeSplit = rangeString.split(mswCONST.me_MSWBIBUS_CITE_RANGE_SEP)
			for s in myRangeSplit:
				if len(s)==0:
					continue;
				ints = s.split(mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN)
				rangeList.append(ints)
			#print "rangeList=",rangeList
			for rangeCoord in rangeList:
				start = thisRangeStart +int(rangeCoord[0])+len(oBrackets) # the one is for the separator character
				stop = thisRangeStart +int(rangeCoord[1]) +len(oBrackets)
				aRange = self.mswapp.getMSWApplication().ActiveDocument.Range(start,stop)
				#print "aRange=", aRange.Text, " ---start, stop , thisRangeStarts", start, stop,thisRangeStart
				self.mswFormatter.applyStyleNumToRange(aRange,int(rangeCoord[2]))
			allRange = self.mswapp.getMSWApplication().ActiveDocument.Range(firstStart,lastStop)
			allRange.Font.Superscript=self.mswFormatter.isCitationSuperscript()
			allRange.Font.Subscript=self.mswFormatter.isCitationSubscript()
			#print allRange.Text
			#aRange = mswapp.getMSWApplication().ActiveDocument.Range(

