#!/usr/bin/env python
#
# nxt_filer program -- Simple GUI to manage files on a LEGO Mindstorms NXT
# Copyright (C) 2006  Douglas P Lau
#
# This program 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.
#
# This program 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.

import cStringIO
import gtk
import os.path
import urllib2
import nxt.locator
from nxt.brick import FileFinder, FileReader, FileWriter

def read_file(b, fname):
	# FIXME: change to "with" syntax for python 2.5
	# with FileReader(b, fname) as r:
	#	with open(fname, 'wb') as f:
	#		for data in r:
	#			f.write(data)
	r = FileReader(b, fname)
	r.__enter__()
	try:
		f = open(fname, 'wb')
		try:
			for data in r:
				f.write(data)
		finally:
			f.close()
	finally:
		r.__exit__(None, None, None)

class NXTListing(gtk.ListStore):

	def __init__(self, brick):
		gtk.ListStore.__init__(self, str, str)
		self.set_sort_column_id(0, gtk.SORT_ASCENDING)
		self.populate(brick, '*.*')

	def populate(self, brick, pattern):
		# FIXME: change to "with" syntax for python 2.5
		# with FileFinder(b, pattern) as f:
		#	for (fname, size) in f:
		#		print '%s\t%s' % (fname, size)
		f = FileFinder(brick, pattern)
		try:
			for (fname, size) in f:
				self.append((fname, str(size)))
		finally:
			f.__exit__(None, None, None)

def write_file(b, fname, fil):
	# FIXME: change to "with" syntax for python 2.5
	# with FileWriter(b, fname) as w:
	#	for size in w:
	#		print 'Wrote %d bytes' % size
	w = FileWriter(b, fname, fil)
	w.__enter__()
	try:
		for size in w:
			print 'Wrote %d bytes' % size
	finally:
		w.__exit__(None, None, None)

def write_files(b, names):
	for fname in names.split('\r\n'):
		if fname:
			print 'File:', fname
			bname = os.path.basename(fname)
			url = urllib2.urlopen(fname)
			try:
				data = url.read()
			finally:
				url.close()
			print 'name %s, size: %d ' % (bname, len(data))
			fil = cStringIO.StringIO(data)
			try:
				write_file(b, bname, fil)
			finally:
				fil.close()

class NXT_Filer(gtk.Window):
	TARGETS = gtk.target_list_add_uri_targets()

	def __init__(self, brick):
		gtk.Window.__init__(self)
		self.brick = brick
		self.set_border_width(6)
		self.nxt_model = NXTListing(brick)
		h = gtk.HBox()
		h.pack_start(self.make_file_panel(str(brick.sock),
			self.nxt_model), True)
		self.add(h)
		self.connect('destroy', self.quit)

	def make_file_list(self):
		tv = gtk.TreeView()
		tv.set_headers_visible(True)
		tv.set_property('fixed_height_mode', True)
		r = gtk.CellRendererText()
		c = gtk.TreeViewColumn('File name', r, text=0)
		c.set_fixed_width(200)
		c.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
		tv.append_column(c)
		r = gtk.CellRendererText()
		c = gtk.TreeViewColumn('Bytes', r, text=1)
		c.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
		c.set_fixed_width(80)
		tv.append_column(c)

#        	tv.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, self.TARGETS,
#			gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
		tv.enable_model_drag_dest(self.TARGETS, gtk.gdk.ACTION_COPY)
#		tv.connect("drag_data_get", self.drag_data_get_data)
		tv.connect("drag_data_received", self.drag_data_received_data)

		return tv

	def make_file_panel(self, name, model):
		v = gtk.VBox()
		v.pack_start(gtk.Label(name), False)
		tv = self.make_file_list()
		tv.set_model(model)
		s = gtk.ScrolledWindow()
		s.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
		s.add(tv)
		s.set_border_width(2)
		v.pack_start(s, True)
		return v

	def drag_data_get_data(self, treeview, context, selection, target_id,
	    etime):
		treeselection = treeview.get_selection()
		model, iter = treeselection.get_selected()
		data = model.get_value(iter, 0)
		print data
		selection.set(selection.target, 8, data)

	def drag_data_received_data(self, treeview, context, x, y, selection,
	    info, etime):
		if context.action == gtk.gdk.ACTION_COPY:
			write_files(self.brick, selection.data)
		# FIXME: update file listing after writing files
		# FIXME: finish context

	def quit(self, w):
		'Quit the program'
		self.brick.sock.close()
		gtk.main_quit()

if __name__ == '__main__':
	# FIXME: add dialog with progress bar when scanning bluetooth devices
	sock = nxt.locator.find_one_brick()
	if sock:
		b = sock.connect()
		win = NXT_Filer(b)
		win.show_all()
		gtk.main()
