#!/usr/bin/env python
#
#Copyright (C) 2008 Przemyslaw Firszt
#
#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.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
import os
import sys
import cairo
import pango
import gobject
import commands
import gtk
import time
import datetime
import screenlets
from screenlets.options import FloatOption, BoolOption, StringOption, FontOption, ColorOption, IntOption


#use gettext for translation
import gettext

_ = screenlets.utils.get_translator(__file__)

def tdoc(obj):
	obj.__doc__ = _(obj.__doc__)
	return obj

@tdoc
class NetSpeedScreenlet(screenlets.Screenlet):
	"""An applet that displays current upload/download speed of selected device"""
	
	# default meta-info for Screenlets
	__name__ = 'NetSpeed'
	__version__ = '0.2'
	__author__ = 'Przemyslaw Firszt'
	__desc__ =__doc__

	__timeout = None
	__update_interval = 1 # every second
	__buffer = None

	x=250
	y=200
	# set theme
	theme_name = "default"

	time_epoch = 0
	upload= 0
	download =0
	upload_speed = '0 B'
	download_speed = '0 B'

	net_device = 'lo'
	
	def __init__(self, **keyword_args):
		"""The constructor. """
		screenlets.Screenlet.__init__(self, width=250, height=100, **keyword_args)
		self.x=250
		self.y=200
		# set theme
		self.theme_name = "default"
		self.add_default_menuitems()

		self.time_epoch = 0
		self.upload= 0
		self.download =0
		self.upload_speed = '0 B'
		self.download_speed = '0 B'
		
		self.net_devices = self.get_network_devices()
		self.net_device = 'lo'
		self.add_options_group(_('Options'), '')
		self.add_option(StringOption(_('Options'), 'net_device', self.net_device, _('Select Device'), '', choices=self.net_devices))
#		self.add_option(IntOption(_('Options'), 'update_interval', 
#			1, _('Update interval'), _('The interval for updating the NetSpeed applet in seconds.'),
#			min=1, max=60))

		self.__timeout = gobject.timeout_add(1000, self.update)

	def get_network_devices(self): #TODO: move to utils.py or sensors.py
		"""This function returns list of names of network devices. The names are extracted from /proc/net/dev/."""
		
		net_devices = []
		try:
			data = commands.getoutput("cat /proc/net/dev |grep :")
			for a_line in data.splitlines():
				if a_line != None and a_line.find(':') != -1 and not a_line.startswith('0'):  
					net_devices.append(str(a_line).split(':')[0])
		except:
			pass #TODO: write something to logfile
		return net_devices
		
	def get_network_traffic(self,net_device): #TODO: move to utils.py or sensors.py
		"""Returns network traffic for gives device in B as a tuple. Format upload/download. Returns 0,0 when there is an error"""
		try:
			file = open("/proc/net/dev", "r")
			data	 = file.readlines(2000)
			file.close()
			upload = 0
			download = 0
			for i in data:
				if i.find(':') != -1 and i.strip().startswith(net_device) == True:
					v = i.split(':')[1].split()
					upload = float( v[8] )
					download = float( v[0] )
			return upload, download
		except:
			return 0,0

	def __setattr__(self, name, value):
		# call Screenlet.__setattr__ in baseclass (ESSENTIAL!!!!)
		screenlets.Screenlet.__setattr__(self, name, value)

	def get_network_speed(self):
		#get upload/download
		upload,download = self.get_network_traffic(self.net_device)
		#get epoch time - it's easier to calculate the delta
		time_now = datetime.datetime.now()
		time_epoch = time.mktime(time_now.timetuple())
		
		#calculate the transfer speed
		upload_delta = upload - self.upload  
		download_delta = download  - self.download
		time_delta = time_epoch - self.time_epoch
		try:
			upload_speed = upload_delta / time_delta
			download_speed = download_delta / time_delta
			#store upload,download and time for next calculation cycle
			self.upload = upload
			self.download = download
			self.time_epoch = time_epoch
		except ZeroDivisionError:
			#Do nothing - cannot calculate speed with time_delta = 0
			pass


		#store upload/download  - on_draw function reads it and displays
		upload_unit="B"
		if upload_speed < 1024: 
			upload_format = "%.0f" 
		else:
			upload_format = "%.1f" #transfer unit is bigger that B so we want to show something after the dot
		if upload_speed>1024: #if the speed was below 1024 kB/s we have proper unit, but we have to check it
			upload_unit='kB'
			upload_speed=upload_speed/1024 
		if upload_speed>1024:#if the speed was below 1024 MB/s we have proper unit (if you have faster connection - let me know)
			upload_unit='MB'
			upload_speed=upload_speed/1024 			
		download_unit="B"
		if download_speed < 1024: 
			download_format = "%.0f" 
		else:
			download_format = "%.1f" #transfer unit is bigger that B so we want to show something after the dot
		if download_speed>1024: #if the speed was below 1024 kB/s we have proper unit, but we have to check it
			download_unit='kB'
			download_speed=download_speed/1024 
		if download_speed>1024:#if the speed was below 1024 MB/s we have proper unit (if you have faster connection - let me know)
			download_unit='MB'
			download_speed=download_speed/1024 
		self.upload_speed = upload_format %(upload_speed) + " " + upload_unit 
		self.download_speed = download_format %(download_speed) + " " + download_unit
		
	def on_draw(self, ctx):		
		if self.theme:		
			ctx.scale(self.scale , self.scale)
			ctx.save()			
			self.theme.render(ctx, 'background')
			ctx.translate(10,10)
			self.theme.render(ctx, 'up')
			ctx.translate(10,40)
			self.theme.render(ctx, 'down')
			ctx.restore()	
			ctx.set_source_rgba(1, 1, 1, 1)
			self.draw_text(ctx, self.upload_speed, 70, 5, "FreeSans", 32, self.width)			
			self.draw_text(ctx, self.download_speed, 70, 45, "FreeSans", 32, self.width)			
			ctx.save()
			self.theme.render(ctx, 'glass')
			ctx.restore()
			
	def update (self):	
		self.get_network_speed()
		self.redraw_canvas()
		return True

	def on_draw_shape(self,ctx):
		self.on_draw(ctx)

if __name__ == "__main__":
	import screenlets.session
	screenlets.session.create_session(NetSpeedScreenlet)
