#!/usr/bin/env python
helpMsg = '''DropboxPath - Change the name or move your DropBox folder.

Of course, NO WARRANTIES, you CAN LOSE files, yadda yadda... Backup first.

Instructions:
- BACKUP YOUR DROPBOX
- Close the dropbox client (right click it, select exit)
- Use your OS tools to change the name of the DropBox Folder or
  move it to another location
- Check if the autodetected locations of DropBox database
  AND DropBox folder are right; if not, change it.
- Put your new location of the DropBox folder in the 'New Location' field
- Press the 'Save location' button
- Open dropbox again and you should be set.'''
version = '0.8.2'

'''CHANGELOG
2009-05-25.0.6
	Added darwin; should require someone to test
2009-05-29.0.7
	Using pickles as Arash mentioned
	Changed binascii to base64 module
	Using wx
	Minor misc changes
2009-06-01.0.8
	Working around a possible bug in sqlite3 by opening db after chdir()
2009-06-02.0.8.1
	The workaround was not complete, still opening sqlite with full path
2009-06-02.0.8.2
	Brown paper bag on me :(
	Three times is the charm for doing a simple bug fix.
'''

import os, sys, sqlite3
from base64 import b64encode, b64decode
from pickle import dumps, loads

try:
	import wx
except ImportError:
	print '''You do not have wxPyhton installed.
In Ubuntu:
	Search package manager and install,
	or use 'sudo apt-get install python-wxgtk2.8' if you feel advanced.
In Windows and OSX:
	Go to the wxpython website:
		http://www.wxpython.org/download.php#binaries
	And select the binary package relative to your arch and python version.
	(Please select one of the unicode versions)
'''
	raw_input('Press ENTER to exit...')
	sys.exit(1)

class MainWindow(wx.Frame):
	DatabaseText = None
	CurrentFolderText = None
	NewFolderText = None
	NewFolderBtn = None
	SaveBtn = None
	dbhost = ''
	def __init__(self, parent, title):
		wx.Frame.__init__(self, parent, wx.ID_ANY, title)
		self.CreateStatusBar()
		self.StatusBar.SetStatusText('Waiting.')

		panel = wx.Panel(self, wx.ID_ANY)
		self.panel = panel
		topsizer = wx.BoxSizer(wx.VERTICAL)
		colsizer = wx.GridBagSizer(hgap=5, vgap=5)

		w = wx.StaticText(panel, wx.ID_ANY, 'Dropbox Path Changer v%s' % version)
		w.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
		topsizer.Add(w, 0, wx.CENTER|wx.ALL, 5)
		w = wx.StaticText(panel, wx.ID_ANY, 'READ THIS CAREFULLY')
		w.SetForegroundColour(wx.RED)
		topsizer.Add(w, 0, wx.CENTER|wx.ALL, 5)
		w = wx.TextCtrl(panel, wx.ID_ANY, helpMsg, size=(500,280), style=wx.TE_MULTILINE|wx.TE_READONLY)
		topsizer.Add(w, 0, wx.CENTER, 5)

		w = wx.StaticText(panel, wx.ID_ANY, 'Database location:')
		colsizer.Add(w, pos=(0,0), border=5)
		w = wx.StaticText(panel, wx.ID_ANY, 'None', style=wx.TE_READONLY)
		self.DatabaseText = w
		colsizer.Add(w, pos=(0,1), border=5)
		w = wx.Button(panel, wx.ID_ANY, "Browse...")
		self.DatabaseBtn = w
		self.Bind(wx.EVT_BUTTON, self.OnBrowseDB, w)
		colsizer.Add(w, pos=(0,2), border=5)

		w = wx.StaticText(panel, wx.ID_ANY, 'Current location:')
		colsizer.Add(w, pos=(1,0), border=5)
		w = wx.StaticText(panel, wx.ID_ANY, 'Default Folder Location', style=wx.TE_READONLY)
		self.CurrentFolderText = w
		colsizer.Add(w, pos=(1,1), border=5)

		w = wx.StaticText(panel, wx.ID_ANY, 'New folder location:')
		colsizer.Add(w, pos=(2,0), border=5)
		w = wx.StaticText(panel, wx.ID_ANY, 'None', style=wx.TE_READONLY)
		self.NewFolderText = w
		colsizer.Add(w, pos=(2,1), border=5)
		w = wx.Button(panel, wx.ID_ANY, "Browse...")
		w.Disable()
		self.NewFolderBtn = w
		self.Bind(wx.EVT_BUTTON, self.OnBrowseDBFolder, w)
		colsizer.Add(w, pos=(2,2), border=5)

		topsizer.Add(colsizer, 0, wx.CENTER|wx.ALL, 5)
		w = wx.Button(panel, wx.ID_ANY, "Save new dropbox folder location")
		w.Disable()
		self.SaveBtn = w
		self.Bind(wx.EVT_BUTTON, self.OnSave, w)
		topsizer.Add(w, 0, wx.CENTER|wx.ALL, 5)

		if sys.platform == 'win32' and os.environ.has_key('APPDATA'):
			dbpath = os.path.join(os.environ['APPDATA'],'Dropbox')
		elif sys.platform in ('linux2','darwin') and os.environ.has_key('HOME'):
			dbpath = os.path.join(os.environ['HOME'],'.dropbox')
		self.DatabaseText.SetLabel('None')
		if os.path.isdir(dbpath):
			dbhost = os.path.join(dbpath, 'host.db')
			if os.path.isfile(dbhost):
				self.dbhost = dbhost
			dbfile = os.path.join(dbpath, 'dropbox.db')
			if os.path.isfile(dbfile):
				self.DatabaseText.SetLabel(dbfile)
				self.DatabaseSelected()
		self.SetSize(wx.Size(510, 550))
		#panel.SetAutoLayout(True)
		panel.SetSizer(topsizer)
		#topsizer.Fit(panel)
		#topsizer.SetSizeHints(panel)
		panel.Layout()
		self.SetClientSize(panel.GetBestSize())


	def DatabaseSelected(self):
		dbfile = self.DatabaseText.GetLabel()
		try:
			lastdir = os.getcwd()
			os.chdir(os.path.dirname(dbfile))
			con = sqlite3.connect(os.path.basename(dbfile), isolation_level=None)
			os.chdir(lastdir)
			cur = con.cursor()
			cur.execute('SELECT value FROM config WHERE key="dropbox_path"')
			row = cur.fetchone()
			cur.close()
			con.close()
			if row is not None:
				dbfolder = loads(b64decode(row[0]))
			else:
				dbfolder = 'Default Location'
			self.CurrentFolderText.SetLabel(dbfolder)
			self.StatusBar.SetStatusText('Database read successfully. Select new location.')
			self.NewFolderBtn.Enable()
			self.NewFolderBtn.SetFocus()
			self.NewFolderText.SetLabel('None')
		except Exception, e:
			self.StatusBar.SetStatusText('Got exception: '+e.message)
			self.DatabaseBtn.SetFocus()
			self.NewFolderBtn.Disable()
			self.CurrentFolderText.SetLabel('None')
		#print self.CurrentFolderText.GetLabel()
		if not self.IsMaximized():
			self.SetClientSize(self.panel.GetBestSize())


	def OnBrowseDB(self, event):
		dbpath = os.path.dirname(self.DatabaseText.GetLabel())
		dlg = wx.FileDialog(self.panel, message='Select Dropbox Database',
			style=wx.FD_OPEN, defaultDir=dbpath, defaultFile='dropbox.db',
			wildcard='DB files (*.db)|*.db')
		if dlg.ShowModal() != wx.ID_OK:
			return
		dbfile = dlg.GetPath()
		dlg.Destroy()
		dbhost = os.path.join(os.path.dirname(dbfile), 'host.db')
		if os.path.isfile(dbhost):
			self.dbhost = dbhost
		if os.path.isfile(dbfile):
			self.DatabaseText.SetLabel(dbfile)
			self.DatabaseSelected()
		#print self.DatabaseText.GetLabel()
		if not self.IsMaximized():
			self.SetClientSize(self.panel.GetBestSize())


	def OnBrowseDBFolder(self, event):
		dlg = wx.DirDialog(self.panel, message='Select current (new) Dropbox Folder location',
			style=wx.DD_DIR_MUST_EXIST)
		if dlg.ShowModal() != wx.ID_OK:
			return
		dbfolder = dlg.GetPath()
		dlg.Destroy()
		if os.path.isdir(dbfolder):
			self.NewFolderText.SetLabel(dbfolder)
			self.StatusBar.SetStatusText('New folder selected. Press the save button to change dropbox.')
			self.SaveBtn.Enable()
		else:
			self.SaveBtn.Disable()
		#print self.NewFolderText.GetLabel()
		if not self.IsMaximized():
			self.SetClientSize(self.panel.GetBestSize())
	
	def OnSave(self, event):
		dbfile = self.DatabaseText.GetLabel()
		dbfolder = self.NewFolderText.GetLabel()
		b64path = b64encode(dumps(dbfolder))
		try:
			lastdir = os.getcwd()
			os.chdir(os.path.dirname(dbfile))
			con = sqlite3.connect(os.path.basename(dbfile), isolation_level=None)
			os.chdir(lastdir)
			cur = con.cursor()
			cur.execute('REPLACE INTO config (key,value) VALUES ("dropbox_path",?)', (b64path,))
			cur.close()
			con.close()
			self.CurrentFolderText.SetLabel(dbfolder)
			msg = 'Location changed successfully!'
			if os.path.isfile(self.dbhost):
				try:
					os.unlink(self.dbhost)
					msg += ' (host.db removed)'
				except Exception, e:
					msg += ' (could not remove host.db)'
			self.StatusBar.SetStatusText(msg)
		except Exception, e:
			self.StatusBar.SetStatusText('Got exception: '+e.message)
		self.NewFolderBtn.SetFocus()
		self.SaveBtn.Disable()


class MyApp(wx.App):
	def OnInit(self):
		frame = MainWindow(None, 'DropboxPath')
		self.SetTopWindow(frame)
		frame.Show(True)
		return True


app = MyApp(0)
#app = MyApp(redirect=True)
app.MainLoop()
