# 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 mswCONST
import pywintypes
from pywintypes import * 
""" This file contains a set of utilities used to manage MS Word citations
More of the functions have self-explanatory names
"""
def getXmlKeysFromString(aString):
	"""Returns a list of all the XML style keys from a String"""
	if aString == None:
		return None
	keys=[]
	mySplit=aString.split("<")
	for myWord in mySplit:
		if len(myWord)<1:
			continue
		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 getXmlValueFromString(key,stringToParse):
	"""Returns a value using XML tag from a String"""
	if key==None or stringToParse == None:
		return None
	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 replaceXmlValueForKey(key,stringToParse,newValue):
	"""Replaces a value inserted between two XML keys"""
	if key==None or stringToParse == None:
		return None
	start = stringToParse.find("<"+key+">")
	if start ==-1:
		return None
	start = start + len(key)+2
	end = stringToParse.find("</"+key+">")
	if end ==-1:
		return None
	stringToReplace = stringToParse[start:end]
	stringToReplace =("<"+key+">")+stringToReplace+("</"+key+">")
	#print "should Replace = ",stringToReplace
	newValue = ("<"+key+">")+newValue+("</"+key+">")
	stringToParse=stringToParse.replace(stringToReplace,newValue)
	return stringToParse

def modifyFieldCodeForKey(amswField,key,newValue):
	"""It access the information with a field and modify its code
	It has to be done this way, otherwise crucial information is lost
	Indeed the Field.Data is lost when Code/Result information is modified"""
	myData=amswField.Data 
	#myResult= amswField.Result.Text 
	myCode = amswField.Code.Text 
	amswField.Code.Text = replaceXmlValueForKey(key,myCode,newValue)
	amswField.Data = myData
	return amswField

	
def isFieldCitation(mswField):
	try:
		if mswField.Data == mswCONST.me_MSWBIBUS_CITE_TAG:
			return True
		else:
			return False
	except (pywintypes.com_error): #Not an addin field (faster than to use isFieldAddin)
		return False

def isFieldBiblio(mswField):
	try:
		if mswField.Data == mswCONST.me_MSWBIBUS_BIBLIO_TAG:
			return True
		else:
			return False
	except (pywintypes.com_error):
		return False
	
def isFieldAddin(mswField):
	if mswField.Type != mswCONST.me_wdFieldAddin:
		return False
	return True

def getCitationFields(mswFields):
	"""Returns all the citation fields from a MS Word Fields collection"""
	citationFields = []
	for myField in mswFields:
		if isFieldCitation(myField)==True:
			citationFields.append(myField)
	return citationFields

def stripStringsFromList(aString,listOfStrings):
	for aSub in listOfStrings:
		aString=aString.replace(aSub,"")
	return aString

	
def moveFieldAfterField(fieldToMove,fieldNoMove):
	""" Very important fieldToMove is deleted during the procedure. Use the return value to recover the field.
	This function swap two fields, used for sorting the fields during fusion
	"""
	lenToex = len(fieldToMove.Result.Text)
	fCode = fieldToMove.Code.Text
	fData = fieldToMove.Data
	fieldToMove.Cut()
	activeDoc = fieldNoMove.Application.ActiveDocument
	aRange = activeDoc.Range(fieldNoMove.Result.End+1,fieldNoMove.Result.End+1)
	newField = activeDoc.Fields.Add(aRange, mswCONST.me_wdFieldEmpty,"toReplace",0)
	newField.Result.PasteAndFormat(0x0)
	newField.Code.Text = fCode
	newField.Data = fData
	fieldToMove = newField
	return fieldToMove
	
	
def correctCodeTextAfterFusion(codeText,mswFormatter):
	"""#if citation are fused it is necessary to correct start values
	#because we insert fuse separator at the begining of each citation"""

	oB,cB =mswFormatter.getBracket()
	rangeString = getXmlValueFromString(mswCONST.me_MSWBIBUS_CITE_RANGES,codeText)
	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)
	newRangeList = []
	for ar in rangeList:
		newNumbersStr=[]
		for abound in ar[:-1]: #last position is a style number
			inta = int(abound)
			inta =inta + len(mswFormatter.getCitationFuseSeparator()) - len(oB)
			newNumbersStr.append(str(inta))
		newNumbersStr.append(ar[-1])
		newRangeList.append(newNumbersStr)
	newRangeString = ""
	for ar in newRangeList: #newRangeList contains a list for fields (ar is one field)
		newRangeString=newRangeString+mswCONST.me_MSWBIBUS_CITE_RANGE_SEP+ar[0]
		for ab in ar[1:]: #each ab is a number,  first, end and the last number is the style
			newRangeString=newRangeString+mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN+ab
	#print getXmlValueFromString(mswCONST.me_MSWBIBUS_CITE_RANGES,codeText),"\n",newRangeString
	#print codeText
	newCodeText = replaceXmlValueForKey(mswCONST.me_MSWBIBUS_CITE_RANGES,codeText,newRangeString)
	#print newCodeText
	return newCodeText
	
def insertField(fieldToInsert,fieldNoMove,mswFormatter):
	activeDoc = fieldNoMove.Application.ActiveDocument
	aRange = activeDoc.Range(fieldNoMove.Result.End+1,fieldNoMove.Result.End+1)
	newField = activeDoc.Fields.Add(aRange, mswCONST.me_wdFieldEmpty,"insert test",0)
	newField.Result.Text = fieldToInsert.Result.Text
	newField.Code.Text =  unicode(fieldToInsert.Code.Text)
	#newField.Code.Text =  "ADDIN BibusRef"
	#print "is Addin insert = ", isFieldAddin(fieldToInsert), " for ", fieldToInsert.Result.Text, " Field Type = ",fieldToInsert.Type
	#print "is Addin newfield= ", isFieldAddin(newField), " for ", newField.Result.Text, " Field Type = ",newField.Type
	#print "Field code = ", newField.Code.Text
	#print "Working on field", newField.Result.Text 
	if mswFormatter.isCitationFused():
		newField.Code.Text = correctCodeTextAfterFusion(fieldToInsert.Code.Text,mswFormatter)
	#else:		
	#	newField.Code.Text = fieldToInsert.Code.Text
	#newField.Data = mswCONST.me_MSWBIBUS_CITE_TAG
	newField.Result.Text = fieldToInsert.Result.Text
	return newField

	
