# Copyright (C) 2007 daelstorm. All rights reserved.
#
# 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 3 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.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Original copyright below
# Copyright (c) 2003-2004 Hyriand. All rights reserved.

import gtk
from thread import start_new_thread

from transferlist import TransferList
from utils import PopupMenu, PressHeader
from pynicotine import slskmessages
import string, os
from pynicotine.utils import _, executeCommand
from entrydialog import *

class Downloads(TransferList):
	def __init__(self, frame):
		TransferList.__init__(self, frame, frame.DownloadList)
		self.frame.DownloadList.set_property("rules-hint", True)
		self.accel_group = gtk.AccelGroup()
		
		
		self.popup_menu2 = popup2 = PopupMenu(frame)
		popup2.setup( 
		        ("#" + _("Clear finished/aborted"), self.OnClearFinishedAborted, gtk.STOCK_CLEAR),
			("#" + _("Clear finished"), self.OnClearFinished, gtk.STOCK_CLEAR),
			("#" + _("Clear aborted"), self.OnClearAborted, gtk.STOCK_CLEAR),
			("#" + _("Clear paused"), self.OnClearPaused, gtk.STOCK_CLEAR),
			("#" + _("Clear filtered"), self.OnClearFiltered, gtk.STOCK_CLEAR),
			("#" + _("Clear queued"), self.OnClearQueued, gtk.STOCK_CLEAR),
		)
		self.popup_menu_users = PopupMenu(frame)

		self.popup_menu = popup = PopupMenu(frame)
		popup.setup(
			("#" + _("Get place in _queue"), self.OnGetPlaceInQueue, gtk.STOCK_INDEX),
			("", None),
			("#" + _("Copy _URL"), self.OnCopyURL, gtk.STOCK_COPY),
			("#" + _("Copy folder URL"), self.OnCopyDirURL, gtk.STOCK_COPY),
			("#" + _("Send to _player"), self.OnPlayFiles, gtk.STOCK_MEDIA_PLAY),
			("#" + _("View Metadata of file(s)"), self.OnDownloadMeta, gtk.STOCK_PROPERTIES),
			("#" + _("Open Directory"), self.OnOpenDirectory, gtk.STOCK_OPEN),
			("#" + _("Search"), self.OnFileSearch, gtk.STOCK_FIND),
			(1, _("User(s)"), self.popup_menu_users, self.OnPopupMenuUsers),
			("", None),
			("#" + _("_Retry"), self.OnRetryTransfer, gtk.STOCK_REDO),
			("", None),
			("#" + _("Abor_t"), self.OnAbortTransfer, gtk.STOCK_CANCEL),
			("#" + _("Abort and remove _file(s)"), self.OnAbortRemoveTransfer, gtk.STOCK_DELETE),
			("#" + _("_Clear"), self.OnClearTransfer, gtk.STOCK_CLEAR),
			("", None),
			(1, _("Clear Groups"), self.popup_menu2, None),
		)
		frame.DownloadList.connect("button_press_event", self.OnPopupMenu, "mouse")
		frame.DownloadList.connect("key-press-event", self.on_key_press_event)
		cols = frame.DownloadList.get_columns()
		for i in range (9):
			parent = cols[i].get_widget().get_ancestor(gtk.Button)
			if parent:
				parent.connect('button_press_event', PressHeader)
			# Read Show / Hide column settings from last session
			cols[i].set_visible(self.frame.np.config.sections["columns"]["downloads"][i])
		frame.clearFinishedAbortedButton.connect("clicked", self.OnClearFinishedAborted)
		frame.clearQueuedButton.connect("clicked", self.OnTryClearQueued)
		frame.retryTransferButton.connect("clicked", self.OnRetryTransfer)
		frame.abortTransferButton.connect("clicked", self.OnSelectAbortTransfer)
		frame.deleteTransferButton.connect("clicked", self.OnAbortRemoveTransfer)
		frame.banDownloadButton.connect("clicked", self.OnBan)
		frame.DownloadList.expand_all()
		
		self.frame.ToggleAutoRetry.set_active(self.frame.np.config.sections["transfers"]["autoretry_downloads"])
		frame.ToggleAutoRetry.connect("toggled", self.OnToggleAutoRetry)
		
		self.frame.ToggleTreeDownloads.set_active(self.frame.np.config.sections["transfers"]["groupdownloads"])
		frame.ToggleTreeDownloads.connect("toggled", self.OnToggleTree)
		self.OnToggleTree(None)
		self.frame.ExpandDownloads.set_active(self.frame.np.config.sections["transfers"]["downloadsexpanded"] )
		frame.ExpandDownloads.connect("toggled", self.OnExpandDownloads)
		self.OnExpandDownloads(None)
		
	def saveColumns(self):
		columns = []
		for column in self.frame.DownloadList.get_columns():
			columns.append(column.get_visible())
		self.frame.np.config.sections["columns"]["downloads"] = columns
		
	def OnToggleAutoRetry(self, widget):
		self.frame.np.config.sections["transfers"]["autoretry_downloads"] = self.frame.ToggleAutoRetry.get_active()
		
	def OnTryClearQueued(self, widget):
		direction="down"
		win = OptionDialog(self.frame, _("Clear All Queued Downloads?"), modal=True, status=None, option=False, third="")
		win.connect("response", self.frame.on_clear_response, direction)
		win.set_title(_("Nicotine+")+": "+_("Clear Queued Transfers"))
		win.set_icon( self.frame.images["n"])
		win.show()
	def expandcollapse(self, path):
		if self.frame.ExpandDownloads.get_active():
			self.frame.DownloadList.expand_row(path, True)
		else:
			self.frame.DownloadList.collapse_row(path)
	def OnExpandDownloads(self, widget):
		expanded = self.frame.ExpandDownloads.get_active()
		if expanded:
			self.frame.DownloadList.expand_all()
			self.frame.ExpandDownloadsImage.set_from_stock(gtk.STOCK_REMOVE, 4)
		else:
			self.frame.DownloadList.collapse_all()
			self.frame.ExpandDownloadsImage.set_from_stock(gtk.STOCK_ADD, 4)
		self.frame.np.config.sections["transfers"]["downloadsexpanded"] = expanded
		self.frame.np.config.writeConfiguration()
	def OnToggleTree(self, widget):
		self.TreeUsers = self.frame.ToggleTreeDownloads.get_active()
		self.frame.np.config.sections["transfers"]["groupdownloads"] = self.TreeUsers
		if not self.TreeUsers:
			self.frame.ExpandDownloads.hide()
		else:
			self.frame.ExpandDownloads.show()
		self.RebuildTransfers()

	def MetaBox(self, title="Meta Data", message="", data=None, modal= True, Search=False):
		win = MetaDialog( self.frame, message,  data, modal, Search=Search)
		win.set_title(title)
		win.set_icon(self.frame.images["n"])
		win.set_default_size(300, 100)
		win.show()
		gtk.main()
		return win.ret
	
	def SelectedResultsAllData(self, model, path, iter, data):
		if iter in self.selected_users:
			return

		user = model.get_value(iter, 0)
		filename = model.get_value(iter, 1)
		fullname = model.get_value(iter, 10)
		size = speed = "0"
		length = bitrate = None
		queue = immediate = num = country = bitratestr = ""
		for transfer in self.frame.np.transfers.downloads:
			if transfer.user == user and fullname == transfer.filename:
				size = self.Humanize(transfer.size, None)
				try:
					speed = str(int(transfer.speed))
					speed += _(" KB/s")
				except: pass
				bitratestr = str(transfer.bitrate)
				length = str(transfer.length)
		directory = fullname.rsplit("\\", 1)[0]

		data[len(data)] = {"user":user, "fn": fullname, "position":num, "filename":filename, "directory":directory, "size":size, "speed":speed, "queue":queue, "immediate":immediate, "bitrate":bitratestr, "length":length, "country":country}

		
	def OnDownloadMeta(self, widget):
		if not self.frame.np.transfers:
			return
		data = {}
		self.widget.get_selection().selected_foreach(self.SelectedResultsAllData, data)

		if data != {}:	
			self.MetaBox(title=_("Nicotine+:")+" "+_("Downloads Metadata"), message=_("<b>Metadata</b> for Downloads"), data=data, modal=True, Search=False)
			
	def OnOpenDirectory(self, widget):

		downloaddir =  self.frame.np.config.sections["transfers"]["downloaddir"]
		incompletedir = self.frame.np.config.sections["transfers"]["incompletedir"]
		if incompletedir == "":
			incompletedir = downloaddir
		filemanager_config = self.frame.np.config.sections["ui"]["filemanager"]
		transfer = self.selected_transfers[0]

		filemanager = filemanager_config.split()[0]
		filemanager_args = filemanager_config.split(filemanager)[1]
		arg = filemanager_args.split('$')[0].strip()
		complete_path = os.path.join(downloaddir, transfer.path)
		arg_list = []
		arg_list.append(filemanager)

		for i in arg.split():
			arg_list.append(i)

		if transfer.path is "":
			if transfer.status is "Finished":
				arg_list.append(downloaddir)
			else:
				arg_list.append(incompletedir)
		elif os.path.exists(complete_path): # and tranfer.status is "Finished"
			arg_list.append(complete_path)
		else:
			arg_list.append(incompletedir)
		#os.system("%s %s &")
		os.spawnvp(os.P_WAIT, filemanager, arg_list)
	
	def RebuildTransfers(self):
		if self.frame.np.transfers is None:
			return
		self.Clear()
		self.update()

	def select_transfers(self):
		self.selected_transfers = []
		self.selected_users = []
		self.widget.get_selection().selected_foreach(self.SelectedTransfersCallback)
		
	def OnBan(self, widgets):
		self.select_transfers()
		for user in self.selected_users:
			self.frame.BanUser(user)
			
	def OnSelectAbortTransfer(self, widget):
		self.select_transfers()
		self.OnAbortTransfer(widget, False)
		
	def OnSelectUserTransfer(self, widget):
		if len(self.selected_users) == 0:
			return
		selected_user = widget.parent.user
		
		sel = self.frame.DownloadList.get_selection()
		fmodel = self.frame.DownloadList.get_model()
		sel.unselect_all()
		
		for item in self.transfers:
			user_file, iter, transfer = item
			user, filepath = user_file
			if selected_user == user:
				ix = fmodel.get_path(iter)
				sel.select_path(ix,)
					
		self.select_transfers()
	def on_key_press_event(self, widget, event):
		key = gtk.gdk.keyval_name(event.keyval)

		if key in ( "P", "p"):
			self.OnPopupMenu(widget, event, "keyboard")
		else:
			self.select_transfers()
			
			if key in ( "T", "t"):
				self.OnAbortTransfer(widget)
			elif key in ( "R", "r"):
				self.OnRetryTransfer(widget)
			elif key == "Delete":
				self.OnAbortTransfer(widget, True, True)

	def OnPlayFiles(self, widget, prefix = ""):
		start_new_thread(self._OnPlayFiles, (widget, prefix))
	def _OnPlayFiles(self, widget, prefix = ""):
		executable = self.frame.np.config.sections["players"]["default"]
		downloaddir = self.frame.np.config.sections["transfers"]["downloaddir"]
		if "$" not in executable:
			return
		for fn in self.selected_transfers:
			if fn.file is None:
				continue
			playfile = None
			if os.path.exists(fn.file.name):
				playfile = fn.file.name
			else:
				"""
If this file doesn't exist anymore, it may have finished downloading and have been
renamed, try looking in the download directory and match the original filename.
				"""
				basename = string.split(fn.filename, '\\')[-1]
				path = os.sep.join([downloaddir, basename])
				if os.path.exists(path):
					playfile = path
			if playfile:
				executeCommand(executable, playfile, background=False)

	def OnPopupMenuUsers(self, widget):
		
		self.selected_transfers = []
		self.selected_users = []
		self.widget.get_selection().selected_foreach(self.SelectedTransfersCallback)
	
		self.popup_menu_users.clear()
		if len(self.selected_users) > 0:
			items = []
			self.selected_users.sort(key=str.lower)
			for user in self.selected_users:
				popup =  PopupMenu(self.frame)
				popup.setup(
					("#" + _("Send _message"), popup.OnSendMessage, gtk.STOCK_EDIT),
					("#" + _("Show IP a_ddress"), popup.OnShowIPaddress, gtk.STOCK_NETWORK),
					("#" + _("Get user i_nfo"), popup.OnGetUserInfo, gtk.STOCK_DIALOG_INFO),
					("#" + _("Brow_se files"), popup.OnBrowseUser, gtk.STOCK_HARDDISK),
					("#" + _("Gi_ve privileges"), popup.OnGivePrivileges, gtk.STOCK_JUMP_TO),
					("", None),
					("$" + _("_Add user to list"), popup.OnAddToList),
					("$" + _("_Ban this user"), popup.OnBanUser),
					("$" + _("_Ignore this user"), popup.OnIgnoreUser),
					("#" + _("Select User's Transfers"), self.OnSelectUserTransfer, gtk.STOCK_INDEX),
					)
				popup.set_user(user)

				items.append((1, user, popup, self.OnPopupMenuUser, popup))
			self.popup_menu_users.setup(*items)
		return True
			
	def OnPopupMenuUser(self, widget, popup=None):
		if popup is None:
			return
		menu = popup
		user = menu.user
		items = menu.get_children()
		
		act = False
		if len(self.selected_users) >= 1:
			act = True
		items[0].set_sensitive(act)
		items[1].set_sensitive(act)
		items[2].set_sensitive(act)
		items[3].set_sensitive(act)

		items[6].set_active(user in [i[0] for i in self.frame.np.config.sections["server"]["userlist"]])
		items[7].set_active(user in self.frame.np.config.sections["server"]["banlist"])
		items[8].set_active(user in self.frame.np.config.sections["server"]["ignorelist"])
		
		for i in range(4, 9):
			items[i].set_sensitive(act)
		return True

	def DoubleClick(self, event):
		self.select_transfers()
		dc = self.frame.np.config.sections["transfers"]["download_doubleclick"]
		
		if dc == 1: # Send to player
			self.OnPlayFiles(None)
		elif dc == 2: #File manager
			self.OnOpenDirectory(None)
		elif dc == 3: #Search
			self.OnFileSearch(None)
		elif dc == 4: #Abort
			self.OnAbortTransfer(None, False)
		elif dc == 5: #Clear
			self.OnClearTransfer(None)
		elif dc == 6: #Retry
			self.OnRetryTransfer(None)
			
	def OnPopupMenu(self, widget, event, kind):
		if kind == "mouse":
			if event.button != 3:
				if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
					self.DoubleClick(event)
				return False
		
		self.selected_transfers = []
		self.selected_users = []
		self.widget.get_selection().selected_foreach(self.SelectedTransfersCallback)
		
		users = len(self.selected_users) > 0
		multi_users = len(self.selected_users) > 1
		files = len(self.selected_transfers) > 0
		multi_files = len(self.selected_transfers) > 1
		
		self.SelectCurrentRow(event, kind)
		
		items = self.popup_menu.get_children()
		if users:
			items[7].set_sensitive(True) # Users Menu
		else:
			items[7].set_sensitive(False) # Users Menu

		if files:
			act = True
		else:
			act = False
		items[0].set_sensitive(act) # Place
		items[4].set_sensitive(act) # Send to player
		items[5].set_sensitive(act) # View Meta
		items[6].set_sensitive(act) # File manager
		items[8].set_sensitive(act) # Search filename
			
		
		act = False
		if not multi_files and files:
			act = True
		items[2].set_sensitive(act) # Copy URL
		items[3].set_sensitive(act) # Copy Folder URL
		
		
		if not users or not files:
			# Disable options
			# Abort, Abort and Remove, retry, clear
			act = False
		else:
			act = True
		for i in range(10, 15):
			items[i].set_sensitive(act)

		
		self.popup_menu.popup(None, None, None, 3, event.time)
		if kind == "keyboard":
			widget.emit_stop_by_name("key_press_event")
		elif kind == "mouse":
			widget.emit_stop_by_name("button_press_event")

		return True
		
	def update(self, transfer = None, forced = False):
		TransferList.update(self, transfer, forced)
		if transfer is None and self.frame.np.transfers is not None:
			self.frame.np.transfers.SaveDownloads()

	def OnGetPlaceInQueue(self, widget):
		self.select_transfers()
		for i in self.selected_transfers:
			if i.status != "Queued":
				continue
			self.frame.np.ProcessRequestToPeer(i.user, slskmessages.PlaceInQueueRequest(None, i.filename))
			
	def OnFileSearch(self, widget):
		self.select_transfers()
		for transfer in self.selected_transfers:
			self.frame.SearchEntry.set_text(transfer.filename.rsplit("\\", 1)[1])
			self.frame.ChangeMainPage(None, "search")
			break
		
	def OnRetryTransfer(self, widget):
		self.select_transfers()
		for transfer in self.selected_transfers:
			if transfer.status in ["Finished", "Old"]:
				continue
			self.frame.np.transfers.AbortTransfer(transfer)
			transfer.req = None
			self.frame.np.transfers.getFile(transfer.user, transfer.filename, transfer.path, transfer)
		self.frame.np.transfers.SaveDownloads()

	def OnAbortRemoveTransfer(self, widget):
		self.select_transfers()
		self.OnAbortTransfer(widget, True)
