
import pygtk
import gtk
import genericdl
import urllib
import os
import os.path
import threading
import socket
import time

#in the future we will probably want full urllib2 implementation
#thus supporting cookie files from the commandline and referrers etc.

BUFSIZE = 1024
RATE_UPDATE_INTERVAL = 2.0
SLEEP_TIME = 0.2

class WebDL(genericdl.GenericDL):
	def __init__(self, *args):
		self.rate = 0
		self.sofar = 0
		genericdl.GenericDL.__init__(self, *args)

	def please_exit(self):
		self.rate = 0
		if not self.killflag.isSet():
			self.killflag.set()

	def build_markup(self):
		(h,t) = os.path.split(self.des_file)
		if self.done:
			return "<b>" + self.escaped_markup(t) + "</b> (" + self.format(self.size_total) + ")\n<small>" + self.status + self.escaped_markup(h) + "\nSource: " + self.escaped_markup(self.src_file) + "</small>"
		else:
			return "<b>" + self.escaped_markup(t) + "</b> (" + self.format(self.size_total) + ")\n<small>" + self.status + self.escaped_markup(h) + "\nDownload: " + self.format(self.rate) + "/sec (" + self.format(self.sofar) + ")</small>"

	def run(self):
		self.time_est = -1

		gtk.gdk.threads_enter()
		self.print_log("Starting Download: " + self.get_tail(),
				"arrows-down")
		gtk.gdk.threads_leave()

		try:
			desfp = file(self.des_file, "wb")
		except:
			gtk.gdk.threads_enter()
			self.print_log("Error opening local file: " + self.des_file, gtk.STOCK_DIALOG_ERROR)
			gtk.gdk.threads_leave()
			self.please_exit()
			self.completed()
			return

		try:
			addin = urllib.urlopen(self.src_file)
			sock = socket.fromfd(addin.fileno(), socket.AF_INET,
							socket.SOCK_STREAM)
			sock.setblocking(0)

			self.size_total = int(addin.info()['Content-Length'])
		except:
			gtk.gdk.threads_enter()
			self.print_log("Error opening remote file: " + self.src_file, gtk.STOCK_DIALOG_ERROR)
			gtk.gdk.threads_leave()
			self.please_exit()

		lastd = self.sofar = 0
		self.status = "Downloading to "
		startt = lastt = curt = time.time()

		while True:
			if self.killflag.isSet():
				break

			try:
				buf = sock.recv(BUFSIZE)
				if not buf:
					break
				self.sofar += len(buf)
			except:
				time.sleep(SLEEP_TIME)
				continue
			desfp.write(buf)

			curt = time.time()
			tdelta = curt - lastt
			ddelta = self.sofar - lastd
			self.rate = float(ddelta) / tdelta
			if tdelta > RATE_UPDATE_INTERVAL:
				lastd = self.sofar
				lastt = curt

			self.progress = min(100, int(float(self.sofar) /
						float(self.size_total)* 100.0))
			timesofar = curt - startt
			overallrate = float(self.sofar) / timesofar
			remaining = float(self.size_total - self.sofar)
			self.time_est = remaining / overallrate
			self.update_fields()

		self.rate = 0
		
		sock.shutdown(2)
		sock.close()
		desfp.close()

		urllib.urlcleanup()
		self.completed()
		gtk.gdk.threads_enter()
		if self.sofar != self.size_total and self.size_total > 0:
			self.print_log("Unfinished Download: " +self.get_tail(),
					gtk.STOCK_DIALOG_ERROR)
		else:
			self.print_log("Completed Download: " + self.get_tail(),
					gtk.STOCK_DIALOG_INFO)
		gtk.gdk.threads_leave()

