#!/usr/bin/env python

#    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/>.

#  Originally a Yahoo! Widget by EJSE <http://www.ejse.com>
#  HAL9000Screenlet (c) ported to Screenlets by JayB 2008

import screenlets
from screenlets.options import BoolOption , IntOption
from screenlets import DefaultMenuItem
from datetime import datetime
import gobject
import os
import cairo
import random
from screenlets.sensors import CPUSensor

#use gettext for translation
import gettext

_ = screenlets.utils.get_translator(__file__)

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

@tdoc
class HAL9000Screenlet (screenlets.Screenlet):
	"""Originally a Yahoo! Widget, now ported to Screenlets. HAL9000 will show you how busy your processor is and it will occasionally speak. Original widget is by EJSE - www.ejse.com"""

	# default meta-info for Screenlets (should be removed and put into metainfo)
	__name__	= 'HAL9000Screenlet'
	__version__	= '1.1'
	__author__	= 'JayB'
	__desc__	= __doc__	# set description to docstring of class
	
	#internal variables
	eyeopacity = 0
	fadedin = False
	load = 0
	pipe = None
	lastplayed=-1
	# editable options (options that are editable through the UI)
	int_period = 150
	bool_showbevel = True
	bool_speak = True
	audioDir = 'resources/audio/'
	soundNames = ['hal_mindgoing.wav', 'hal_goingwell.wav', 'hal_daisy.wav', 'hal_tracking.wav', 'hal_9000series.wav', 'hal_cantdothat.wav', 'hal_fault.wav', 'hal_disconnect.wav']
	number = 0
	# constructor
	def __init__ (self, **keyword_args):
		#call super (width/height MUST match the size of graphics in the theme)
		screenlets.Screenlet.__init__(self, width=140, height=140, 
			uses_theme=True, **keyword_args)
		# set theme
		self.theme_name = "default"
		# init CPU sensor
		self.sensor = CPUSensor()
		# add option group
		self.add_options_group(_('HAL9000'), _('Options'))
		# add editable option to the group

		self.add_option(BoolOption(_('HAL9000'),'bool_speak', 
			self.bool_speak, _('Speak'), 
			_('Enable/Disable HAL making sounds...')))

		self.add_option(BoolOption(_('HAL9000'),'bool_showbevel', 
			self.bool_showbevel, _('Show bevel'), 
			_('Enable/Disable bevel (outer border)...')))

		self.add_option(IntOption(_('HAL9000'),'int_period', 
			self.int_period, _('Speak every (sec)'), 
			_('Period after which HAL will speak'), 
			min=30, max=5000))


		# ADD a 50 miliseconds TIMER
		self.timer = gobject.timeout_add( 50, self.update)
		random.seed()

	def send_command (self, command):
		self.pipe.write(command + ' \n')  # \n to end the command
		print command
		self.pipe.close()


	def playsound(self, sound): 
		if self.bool_speak:
			try:
				self.send_command('quit')
			except Exception, ex:
				print 'Still silent'
			mypath=self.get_screenlet_dir()
			self.pipe = os.popen('mplayer -quiet -slave ' + chr(34) + 'file://' + mypath + '/' + self.audioDir + sound + chr(34) , 'w')

	def update (self):
		if self.fadedin == False:
			self.eyeopacity= self.eyeopacity + 0.05
			if self.eyeopacity > 1.1:
				self.fadedin = True
				self.eyeopacity=1
				# Remove a 50 miliseconds TIMER and add 1 second timer
				self.timer = gobject.source_remove(self.timer)
				if int(datetime.now().strftime("%H")) > 17:
					self.playsound('hal_goodevening.wav')
				else:
					self.playsound('hal_operational.wav')
				self.timer = gobject.timeout_add(1000, self.update)
		else:
			self.eyeopacity= 1.0-(self.sensor.get_load()/100.0)
			if self.eyeopacity>1:
				self.eyeopacity=1
			if self.eyeopacity<0.2:
				self.eyeopacity=0.2
			if self.number <= self.int_period:
				self.number = self.number+1
			else:
				temp=self.lastplayed
				while temp==self.lastplayed:
					temp=random.randint(0, 7)
				self.lastplayed=temp
				self.playsound(self.soundNames[temp])
				self.number = 0
		self.redraw_canvas()
		return True # keep running this event	
	
	def on_init (self):
		"""Called when the Screenlet's options have been applied and the 
		screenlet finished its initialization. If you want to have your
		Screenlet do things on startup you should use this handler."""
		# add menu item
		self.add_menuitem("at_runtime", _("Speak!"))
		# add default menu items
		self.add_default_menuitems()
	
	def on_menuitem_select (self, id):
		"""Called when a menuitem is selected."""
		if id == "at_runtime":
			temp=self.lastplayed
			while temp==self.lastplayed:
				temp=random.randint(0, 7)
			self.lastplayed=temp
			self.playsound(self.soundNames[temp])
		pass
	
	def on_mouse_down (self, event):
		"""Called when a buttonpress-event occured in Screenlet's window. 
		Returning True causes the event to be not further propagated."""
		if random.randint(0, 10) > 5:
			self.playsound('hal_justwhat.wav') #HAL doesn't like you touching him!  ;)	    
		return False
	
	def on_quit (self):
		"""Callback for handling destroy-event. Perform your cleanup here!"""
		try:
			self.pipe.write ('quit\n')
		except Exception, ex:
			print 'Still silent'
		try:
			self.pipe.close()
		except Exception, ex:
			print 'Pipe closed'
		return True
	
	def on_draw (self, ctx):
		# if theme is loaded
		if self.theme:
			# set scale rel. to scale-attribute
			ctx.scale(self.scale, self.scale)
			if self.bool_showbevel:
				ctx.set_source_surface(self.theme['bevel.png'], 1, 1)
				ctx.paint()
			ctx.translate(5,5)
			ctx.translate(12,12)
			self.theme.render(ctx, 'bg')
			ctx.translate(2,2)
			# render png-file
			ctx.set_source_surface(self.theme['eye.png'], 1, 0)
			ctx.paint_with_alpha(self.eyeopacity)
			ctx.translate(-13,-13)			
			self.theme.render(ctx, 'hal9000')
	
	def on_draw_shape (self, ctx):
		self.on_draw(ctx)
	
# If the program is run directly or passed as an argument to the python
# interpreter then create a Screenlet instance and show it
if __name__ == "__main__":
	# create new session
	import screenlets.session
	screenlets.session.create_session(HAL9000Screenlet)

