# Copyright (c) 2003-2004 Hyriand. All rights reserved.
#
import gtk
import gobject
import os
import locale
import sys

from utils import recode, InputDialog

from pynicotine.utils import _

class DirNode:
	def __init__(self, parent, name, init = None):
		self.parent = parent
		self.name = name
		if init is not None:
			self._nodes = [DirNode(self, init)]
		else:
			self._nodes = None
	
	def nodes(self):
		if self._nodes is None:
			self._nodes = []
			node = self
			path = ""
			while node:
				path = os.path.join(node.name, path)
				node = node.parent
			try:
				l = os.listdir(path)
			except:
				self._nodes = []
				return self._nodes
				
			l.sort(locale.strcoll)
			for i in l:
				if i[0] == ".":
					continue
				fn = os.path.join(path, i)
				if not os.path.isdir(fn):
					continue
				newnode = DirNode(self, i)
				self._nodes.append(newnode)
		return self._nodes

	def find(self, path):
		self.nodes()
		ix = 0
		for node in self._nodes:
			if node.name == path:
				return node, ix
			ix += 1
		return None, 0
		
class DirTreeModel(gtk.GenericTreeModel):
	def __init__(self):
		gtk.GenericTreeModel.__init__(self)
		self.tree = DirNode(None, "", "/")

	def find_path(self, path):
		if not path:
			return
		if path[-1] == "/":
			path = path[:-1]
		p = []
		while 1:
			path, t = os.path.split(path)
			if t == "":
				p.insert(0, path)
				break
			p.insert(0, t)
		r = []
		node = self.tree
		for i in p:
			node, ix = node.find(i)
			if node is None:
				break
			r.append(ix)
		return tuple(r)
		
	def on_get_flags(self):
		return 0
	
	def on_get_n_columns(self):
		return 2
	
	def on_get_column_type(self, column):
		return gobject.TYPE_STRING
	
	def on_get_path(self, node):
		path = []
		while node.parent != None:
			path.insert(0, node.parent.nodes().index(node))
			node = node.parent
		return tuple(path)
	
	def on_get_iter(self, path):
		node = self.tree
		for i in path:
			node = node.nodes()[i]
		return node
	
	def on_get_value(self, node, column):
		if column == 0:
			return recode(node.name)

		res = node.name
		while node.parent is not None:
			node = node.parent
			res = os.path.join(node.name, res)
		return res
	
	def on_iter_next(self, node):
		try:
			ix = node.parent.nodes().index(node) + 1
			return node.parent.nodes()[ix]
		except IndexError:
			return None
	
	def on_iter_children(self, node):
		try:
			return node.nodes()[0]
		except:
			return None
	
	def on_iter_has_child(self, node):
		return len(node.nodes()) > 0
	
	def on_iter_n_children(self, node):
		return len(node.nodes())
	
	def on_iter_nth_child(self, node, n):
		try:
			return node.nodes()[n]
		except:
			return None
	
	def on_iter_parent(self, node):
		return node.parent

class DirChooser(gtk.Dialog):
	def __init__(self, title = _("Select directory..."), parent = None, initialdir = "~"):
		gtk.Dialog.__init__(self, title, parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        	                    (gtk.STOCK_OK, gtk.RESPONSE_OK,
                	             gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))

		self.set_default_size(300, 400)
		self.set_border_width(10)
		self.vbox.set_spacing(10)

		scrolledwindow = gtk.ScrolledWindow()
		scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
		
		self.model = DirTreeModel()
		
		self.treeview = gtk.TreeView(self.model)
		self.treeview.set_headers_visible(gtk.FALSE)
		scrolledwindow.add(self.treeview)

		column = gtk.TreeViewColumn(_("Directory Tree"), gtk.CellRendererText(), text = 0)
		self.treeview.append_column(column)

		scrolledwindow.show_all()
		self.vbox.pack_start(scrolledwindow, gtk.TRUE, gtk.TRUE)
		
		hbox = gtk.HBox()
		b = gtk.Button(_("Create folder"))
		b.connect("clicked", self.OnMakeDir)
		hbox.pack_end(b, gtk.FALSE, gtk.FALSE)
		hbox.show_all()
		self.vbox.pack_start(hbox, gtk.FALSE, gtk.TRUE)

		if not initialdir:
			initialdir = "~"
		if initialdir == "~" and sys.platform.startswith("win"):
			initialdir = "C:\\My Documents"
		self.initialdir = initialdir
		
	def run(self):
		gobject.idle_add(self.select_path, self.initialdir)
		return gtk.Dialog.run(self)
	
	def select_path(self, path):
		path = self.model.find_path(os.path.expanduser(path))
		if path:
			for i in range(len(path)):
				self.treeview.expand_row(path[:i+1], gtk.FALSE)
			sel = self.treeview.get_selection()
			if sel:
				sel.unselect_all()
				sel.select_path(path)
				self.treeview.scroll_to_cell(path, None, gtk.TRUE, 0.5, 0.5)

	def get_path(self):
		model, iter = self.treeview.get_selection().get_selected()
		if iter is not None:
			return model.get_value(iter, 1)
		else:
			return None

	def OnMakeDir(self, widget):
		path = self.get_path()
		if not path:
			path = ""
		else:
			path += "/"
		newpath = InputDialog(self, _("Make folder..."), _("Enter pathname of new folder:"))
		if not newpath:
			return
		path = os.path.normpath(os.path.join(path, os.path.expanduser(newpath)))
		try:
			os.makedirs(path)
		except:
			dlg = gtk.MessageDialog(self, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _("Could not create folder"))
			dlg.run()
			dlg.destroy()
			self.select_path(path)
			return
			
		if path[:-1] == "/":
			path = path[:-1]
		s = []
		p = path
		while 1:
			p, t = os.path.split(p)
			if t == "":
				s.insert(0, p)
				break
			s.insert(0, t)
		p = ""
		node = self.model.tree
		for part in s:
			newnode, ix = node.find(part)
			p = os.path.join(p, part)
			if newnode is None:
				newnode = DirNode(node, part)
				newnode._nodes = []
				node._nodes.append(newnode)
				_p = self.model.find_path(p)
				_i = self.model.get_iter(_p)
				self.model.emit("row-inserted", _p, _i)
			node = newnode
		self.select_path(path)

def ChooseDir(parent = None, initialdir = "~"):
	dlg = DirChooser(parent = parent, initialdir = initialdir)
	response = dlg.run()
	if response == gtk.RESPONSE_OK:
		res = dlg.get_path()
	else:
		res = None
	dlg.destroy()
	return res

if __name__ == "__main__":
	print ChooseDir()
	