"""Compare local and remote dictionaries and transfer differing files -- like rdist."""

import sys
from repr import repr
import FSProxy
import time
import os

def main():
	pwd = os.getcwd()
	s = raw_input("chdir [%s] " % pwd)
	if s:
		os.chdir(s)
		pwd = os.getcwd()
	host = ask("host", 'voorn.cwi.nl')
	port = 4127
	verbose = 1
	mode = ''
	print """\
Mode should be a string of characters, indicating what to do with differences.
r - read different files to local file system
w - write different files to remote file system
c - create new files, either remote or local
d - delete disappearing files, either remote or local
"""
	s = raw_input("mode [%s] " % mode)
	if s: mode = s
	address = (host, port)
	t1 = time.time()
	local = FSProxy.FSProxyLocal()
	remote = FSProxy.FSProxyClient(address, verbose)
	compare(local, remote, mode)
	remote._close()
	local._close()
	t2 = time.time()
	dt = t2-t1
	mins, secs = divmod(dt, 60)
	print mins, "minutes and", round(secs), "seconds"
	raw_input("[Return to exit] ")

def ask(prompt, default):
	s = raw_input("%s [%s] " % (prompt, default))
	return s or default

def askint(prompt, default):
	s = raw_input("%s [%s] " % (prompt, str(default)))
	if s: return string.atoi(s)
	return default

def compare(local, remote, mode):
	print
	print "PWD =", `os.getcwd()`
	sums_id = remote._send('sumlist')
	subdirs_id = remote._send('listsubdirs')
	remote._flush()
	print "calculating local sums ..."
	lsumdict = {}
	for name, info in local.sumlist():
		lsumdict[name] = info
	print "getting remote sums ..."
	sums = remote._recv(sums_id)
	print "got", len(sums)
	rsumdict = {}
	for name, rsum in sums:
		rsumdict[name] = rsum
		if not lsumdict.has_key(name):
			print `name`, "only remote"
			if 'r' in mode and 'c' in mode:
				recvfile(local, remote, name)
		else:
			lsum = lsumdict[name]
			if lsum != rsum:
				print `name`,
				rmtime = remote.mtime(name)
				lmtime = local.mtime(name)
				if rmtime > lmtime:
					print "remote newer",
					if 'r' in mode:
						recvfile(local, remote, name)
				elif lmtime > rmtime:
					print "local newer",
					if 'w' in mode:
						sendfile(local, remote, name)
				else:
					print "same mtime but different sum?!?!",
				print
	for name in lsumdict.keys():
		if not rsumdict.keys():
			print `name`, "only locally",
			fl()
			if 'w' in mode and 'c' in mode:
				sendfile(local, remote, name)
			elif 'r' in mode and 'd' in mode:
				os.unlink(name)
				print "removed."
			print
	print "gettin subdirs ..."
	subdirs = remote._recv(subdirs_id)
	common = []
	for name in subdirs:
		if local.isdir(name):
			print "Common subdirectory", repr(name)
			common.append(name)
		else:
			print "Remote subdirectory", repr(name), "not found locally"
			if 'r' in mode and 'c' in mode:
				pr = "Create local subdirectory %s? [y] " % \
				     repr(name)
				if 'y' in mode:
					ok = 'y'
				else:
					ok = ask(pr, "y")
				if ok[:1] in ('y', 'Y'):
					local.mkdir(name)
					print "Subdirectory %s made" % \
						repr(name)
					common.append(name)
	lsubdirs = local.listsubdirs()
	for name in lsubdirs:
		if name not in subdirs:
			print "Local subdirectory", repr(name), "not found remotely"
	for name in common:
		print "Entering subdirectory", repr(name)
		local.cd(name)
		remote.cd(name)
		compare(local, remote, mode)
		remote.back()
		local.back()

def sendfile(local, remote, name):
	try:
		remote.create(name)
	except (IOError, os.error), msg:
		print "cannot create:", msg
		return
	
	print "sending ...",
	fl()
	
	data = open(name).read()
	
	t1 = time.time()
	
	remote._send_noreply('write', name, data)
	remote._flush()
	
	t2 = time.time()
	
	dt = t2-t1
	print len(data), "bytes in", round(dt), "seconds",
	if dt:
		print "i.e.", round(len(data)/dt), "bytes/sec",
	print

def recvfile(local, remote, name):
	ok = 0
	try:
		rv = recvfile_real(local, remote, name)
		ok = 1
		return rv
	finally:
		if not ok:
			print "*** recvfile of %s failed, deleting" % `name`
			local.delete(name)

def recvfile_real(local, remote, name):
	try:
		local.create(name)
	except (IOError, os.error), msg:
		print "cannot create:", msg
		return
	
	print "receiving ...",
	fl()
	
	f = open(name, 'w')
	t1 = time.time()
	
	length = 4*1024
	offset = 0
	id = remote._send('read', name, offset, length)
	remote._flush()
	while 1:
		newoffset = offset + length
		newid = remote._send('read', name, newoffset, length)
		data = remote._recv(id)
		id = newid
		if not data: break
		f.seek(offset)
		f.write(data)
		offset = newoffset
	size = f.tell()
	
	t2 = time.time()
	f.close()
	
	dt = t2-t1
	print size, "bytes in", round(dt), "seconds",
	if dt:
		print "i.e.", int(size/dt), "bytes/sec",
	print
	remote._recv(id) # ignored

def fl():
	sys.stdout.flush()

if __name__ == '__main__':
	main()
