# Copyright 2004,2005 Pierre Martineau <pmartino@users.sourceforge.net>
# 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
#
import wx
import BIB,cPickle

class keyDropTarget(wx.PyDropTarget):
	def __init__(self,window):
		wx.PyDropTarget.__init__(self,bibDataObject())
		self.window = window
		self.keytree = window.keytree
		self.currentitem = None
		self.db = window.db
		# data object to store DnD object
		#self.mydata = bibDataObject()
		#self.SetDataObject(self.mydata)

	def OnDragOver(self,x,y,dragReturn):
		pos = wx.Point(x,y)
		item,flags = self.keytree.HitTest(pos)
		if (flags & wx.TREE_HITTEST_ONITEMLABEL) and (self.window.allowed[self.keytree.GetPyData(item)[2]] & (BIB.REF_DROP_OK|BIB.DROP_OK) ):
			#self.keytree.SelectItem(item)
			if self.currentitem != None:
				self.keytree.SetItemBold(self.currentitem,False)
				#self.keytree.SetItemBackgroundColour(self.currentitem,wx.NullColour)
			self.keytree.SetItemBold(item,True)
			#self.keytree.SetItemBackgroundColour(item,wx.LIGHT_GREY)
			self.currentitem = item
		elif flags & wx.TREE_HITTEST_ONITEMBUTTON and not self.keytree.IsExpanded(item):
			self.keytree.Expand(item)
			dragReturn = wx.DragNone
		else:
			dragReturn = wx.DragNone
		return dragReturn

	def OnDrop(self,x,y):
		pos = wx.Point(x,y)
		item,flags = self.keytree.HitTest(pos)
		if (flags & wx.TREE_HITTEST_ONITEMLABEL) and (self.window.allowed[self.keytree.GetPyData(item)[2]] & (BIB.REF_DROP_OK|BIB.DROP_OK) ):
			return True
		else:
			return False

	def OnData(self,x,y,result):
		pos = wx.Point(x,y)
		item,flags = self.keytree.HitTest(pos)
		newparentID,user,id = self.keytree.GetPyData(item)
		if self.GetData():
			mydrag = self.GetDataObject()	# strange. A DataObject instead of a bibDataObject
			if not mydrag.IsSupported(BIB.DnD_FORMAT):
				return
			refdragged = cPickle.loads(mydrag.GetDataHere(BIB.DnD_FORMAT))
			if refdragged.format == BIB.DnD_REF:
				if refdragged.dbInfo == self.db.getDbInfo():
					#""" The dropped data comes from the same database, table => just update the links"""
					for ref in refdragged:
						self.db.writeLink((newparentID,ref[0]))
				else:
					#"""We can just copy and not move"""
					result = wx.DragCopy
					for ref in refdragged:
						if ref[BIB.BIBLIOGRAPHIC_FIELDS['Identifier']]:
							Identifier = ref[BIB.BIBLIOGRAPHIC_FIELDS['Identifier']]
						else:
							Identifier = ref[BIB.BIBLIOGRAPHIC_FIELDS['Author']].split(u',')[0].replace(u' ',u'_')+ ref[BIB.BIBLIOGRAPHIC_FIELDS['Year']]
						ref = (None,Identifier)+ref[2:]
						ref_id = self.db.writeRef(ref)
						if ref_id != None:
							self.db.writeLink((newparentID,ref_id))
			elif refdragged.format == BIB.DnD_KEY and refdragged.dbInfo == self.db.getDbInfo():
				# DnD of key in the same database (does not make sense if the db are differents)
				# we move the key
				result = wx.DragMove
				oldkey_id = refdragged[0]
				allowed=self.window.allowed[id]
				#
				key = newparentID
				drop = True
				rootID = self.db.getRoot(self.keytree.user)[0][0]
				while key != rootID: # check if newparentID is a child (of a child of a child ...) of oldkey_id
					if key == oldkey_id:
						drop = False
						break
					else:
						key = self.db.getKeyParent(self.keytree.user,key)
				#
				oldparentId = self.db.getKeyParent(self.keytree.user,oldkey_id)
				if (allowed & BIB.DROP_OK) and (newparentID != oldparentId) and drop:
					if not self.db.keyExist(self.keytree.user,newparentID,self.db.getKeyName(self.keytree.user,oldkey_id)):	# The new key does not exist
						self.db.modifyKeyParent(self.keytree.user,newparentID,oldkey_id)
						newitem = self.keytree.AppendItem(item,self.db.getKeyName(self.keytree.user,oldkey_id))
						self.keytree.SetPyData(newitem,(oldkey_id,newparentID,BIB.ID_CHILDREN[id]))
						self.keytree.EnsureVisible(newitem)
						if self.db.getKeyChildren(self.keytree.user,oldkey_id):
							self.keytree.SetItemHasChildren(newitem,True)
						else:
							self.keytree.SetItemHasChildren(newitem,False)
					else:
						# the Key exists -> refuse drag&drop
						wx.LogError(_("Sorry but the key you are moving already exist in this folder"))
						result = wx.DragNone
			else:
				result = wx.DragNone
		self.keytree.SetItemBold(item,False)
		return result

	def OnLeave(self):
		if self.currentitem != None:
			self.keytree.SetItemBold(self.currentitem,False)
			#self.keytree.SetItemBackgroundColour(self.currentitem,wx.NullColour)
		#self.keytree.Refresh()

class bibDragData(list):
	def __init__(self,info,format):
		self.dbInfo = info	# info is a tuple/ For MySQL = (host,db,table) ; for SQLite = (file,table)
		self.format = format # format == BIB.DnD_REF or BIB.DnD_KEY depending if we drag a reference or a key

class bibDataObject(wx.CustomDataObject):
	"""DataObject for DnD"""
	def __init__(self):
		wx.CustomDataObject.__init__(self,BIB.DnD_FORMAT)
		self.data = ""

	def setObject(self,data):
		return self.SetData(cPickle.dumps(data,True))

	def getObject(self):
		return cPickle.loads(self.GetDataHere())

class HTMLDataObject(wx.CustomDataObject):
	"""DataObject for DnD"""
	def __init__(self,text):
		wx.CustomDataObject.__init__(self,wx.CustomDataFormat('text/html'))
		self.SetData(text)

	def SetData(self,data):
		if type(data) == unicode:
			wx.CustomDataObject.SetData(self,data.encode('utf-8'))
		elif type(data) == str:
			wx.CustomDataObject.SetData(self,data.decode(BIB.ENCODING).encode('utf-8'))
		else:
			wx.CustomDataObject.SetData(self,data)

class keyDropSource(wx.DropSource):
	def __init__(self,win=None,**args):
		wx.DropSource.__init__(self,win=win,**args)
		self.keytree = win.keytree							# the keytree that initiated the drag event
		self.currentitem = None
	def GiveFeedback(self, effect):
		where = wx.GetMousePosition()						# screen coordinates
		if self.keytree == wx.FindWindowAtPoint(where):
			pt = self.keytree.ScreenToClient(where)				# window coordinates
			item, flags = self.keytree.HitTest(pt)
			if (flags & wx.TREE_HITTEST_ONITEMLABEL) and (self.window.allowed[self.keytree.GetPyData(item)[2]] & BIB.DROP_OK ):
				if self.currentitem != None:
					self.keytree.SetItemBold(self.currentitem,False)
				self.keytree.SetItemBold(item,True)
				self.currentitem = item
			elif flags & wx.TREE_HITTEST_ONITEMBUTTON and not self.keytree.IsExpanded(item):
				self.keytree.Expand(item)
		return True
