#!/usr/bin/env python
# -*- coding: utf-8 -*-

# LinuxEstoniaStats (c) Guido Tabbernuk 2010 <boamaod@gmail.com>
# Idea and some code snippets from: Nemanja Jovicic 2008
# <nemanja.jovicic@hotmail.com>
#
#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 screenlets
from screenlets.options import IntOption
#from screenlets.options import StringOption, IntOption, ColorOption, BoolOption
#import cairo
import gtk
import subprocess
import pango
from os import system
import gobject
from urllib2 import urlopen
import threading
import traceback

# use gettext for translation
import gettext

_ = screenlets.utils.get_translator(__file__)

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

@tdoc
class LinuxEstoniaStatsScreenlet(screenlets.Screenlet):
	"""Shows statistics about Estonian Linux users on Estonian map based on the data of http://counter.li.org/."""

	# default meta-info for Screenlets
	__name__ = 'LinuxEstoniaStats'
	__version__ = '0.0.6'
	__author__ = 'Guido Tabbernuk'
	__desc__ = __doc__

	# internals
	__timeout = None

	__notifier = None
	__lock = threading.Lock()

	# editable options and defaults
	__update_interval = 60*60*24 # every 24h
#	__update_interval = 120 # every 60 sec

	p_layout = None 

	refresh= True

	reload_menu = None

	dealingWithData = False
	
	regions=[]
	cities=[]
	usercount = -1
	usercount_before = -1

	difference = None

	coordinate = {
	'Tallinn': (342, 454),
	'Tartu': (577, 230),
	'Harjumaa': (435, 434),
	'Hiiumaa': (134, 320),
	'Ida-Virumaa': (653, 434),
	'Lääne-Virumaa': (525, 447),
	'Järvamaa': (448, 291),
	'Jõgevamaa': (530, 282),
	'Läänemaa': (252, 352),
	'Parnumaa': (365, 166),
	'Pärnumaa': (370, 164),
	'Põlvamaa': (670, 126),
	'Raplamaa': (346, 349),
	'Saaremaa': (100, 188),
	'Tartumaa': (573, 215),
	'Valgamaa': (539, 124),
	'Võrumaa': (613, 79),
	'Viljandimaa': (458, 162)
	}

	# constructor
	def __init__(self, **keyword_args):
		# call super
		screenlets.Screenlet.__init__(self, width=771, height=502, **keyword_args)
		self.x=250
		self.y=200

		self.__notifier = screenlets.utils.Notifier(self)

		# set theme
		self.theme_name = "default"

		self.add_options_group("","")
		
		self.add_option(IntOption("", "usercount", 
			self.usercount, "Usercount", 
			"Hidden parameter to save previous usercount", 
			min=-1, max=9999999, hidden=True))

	def __setattr__(self, name, value):
		screenlets.Screenlet.__setattr__(self, name, value)

	def on_init (self):

		print "... has started."

		self.add_menuitem("register", _("Register yourself as a Linux user"))
		self.reload_menu = self.add_menuitem("reload", _("Refresh"))

		# add default menu items
		self.add_default_menuitems()

#		print "PEALE INITIT ALUL: ", self.usercount

#		self.usercount_before = self.usercount

#		if self.usercount < 0:
#			self.usercount=0

		# et saaks salvestatud
#		self.usercount += 1
#		self.usercount -= 1

#		print "PEALE INITIT LÕPUS: ", self.usercount


#	def update(self):
#		self.redraw_canvas()

		if self.__timeout:
			gobject.source_remove(self.__timeout)
		self.__timeout = gobject.timeout_add(self.__update_interval * 1000, self.reload_data)

		if not self.dealingWithData:
			self.reload_data()
		

	def on_draw(self, ctx):
		if self.theme:
			ctx.save()
			ctx.scale(self.scale , self.scale)
			self.theme.render(ctx, 'background')
			ctx.restore()

#			print "ON DRAW ALUL KASUTAJAID: ", self.usercount			

			#print self.refresh, self.dealingWithData, len(self.regions)
			#block loading from site
			if len(self.regions) != 0:

				regions_top = sorted(self.regions, key=lambda x: int(x["users"]), reverse=True)

				for x in range(len(regions_top)):
#					print regions_top[x]["name"], regions_top[x]["users"], regions_top[x]["x"], regions_top[x]["y"]

					font_rel_size = int(regions_top[x]["users"])/4+20

					text=regions_top[x]["users"]
					font="Monospace Bold "+str(font_rel_size*self.scale)

#					print regions_top[x]["name"], text, font_rel_size

					bounds = self.get_text_extents(ctx, text, font)

					x_pos = regions_top[x]["x"] - bounds[2]/2
					y_pos = regions_top[x]["y"] - bounds[3]/2
#					x_pos = regions_top[x]["x"] - 7
#					y_pos = regions_top[x]["y"] - 10

					self.draw_text2(ctx, text, x_pos*self.scale, y_pos*self.scale, font, 1, 1, 1, 1)


				cities_top = sorted(self.cities, key=lambda x: int(x["users"]), reverse=True)

				self.draw_text2(ctx,_("Top Cities"),40*self.scale,2*self.scale, "Monospace Bold "+str(12*self.scale),1,1,1,1)
				x_difference=0
				active_line=0
				font_size=12
				line_spacing=15
				y_posoht=0
				for x in range(7):
					self.draw_text2(ctx, cities_top[x]["name"]+": "+cities_top[x]["users"],(60+x_difference)*self.scale,23*self.scale + y_posoht,"Monospace Bold "+str(font_size*self.scale),1,1,1,1)
					x+=1
					active_line+=1
					y_posoht+=line_spacing*self.scale
					if x == 3:
	#					x_difference=100
	#					active_line=0
						font_size=11
					if x == 4:
						font_size=10
						line_spacing=14
					if x == 5:
						font_size=9
						line_spacing=13
					if x == 6:
						line_spacing=12

				#total users			
				self.draw_text2(ctx, str(self.usercount),62*self.scale,400*self.scale,"Monospace Bold "+str(35*self.scale),1,1,1,1)
				self.draw_text2(ctx,_("locally registered Linux users"),47*self.scale,454*self.scale,"Monospace Bold "+str(10*self.scale),1,1,1,1)

				if self.difference is not None:
					self.draw_text2(ctx, "(" + self.difference + ")", 152*self.scale,400*self.scale,"Monospace Bold "+str(35*self.scale),1,1,1,1)
				#drawing circles

			else:
				self.draw_text2(ctx,_("Web query in progress..."),47*self.scale,454*self.scale,"Monospace Bold "+str(10*self.scale),1,1,1,1)


	def on_draw_shape(self, ctx):
		if self.theme:
			self.on_draw(ctx)
	
	def menuitem_callback(self, widget, id):
		screenlets.Screenlet.menuitem_callback(self, widget, id)
		if id == "reload":
			self.reload_data()
		if id == "register":
			subprocess.Popen(["xdg-open", "http://counter.li.org/enter-person.php"])

	def draw_text2(self, ctx, value, x, y, font, r,g,b,a):
		self.draw_text(ctx, value, x+1, y+1, font, 0.5, 0.5, 0.5, 0.5)
		self.draw_text(ctx, value, x, y, font, r, g, b, a)
			
	def draw_text(self, ctx, value, x, y, font, r,g,b,a):
		ctx.save()
		#ctx.translate(x, y)
		ctx.move_to(x, y)
		if self.p_layout == None:		#fixed memory leak
			self.p_layout = ctx.create_layout() 
		else: 
			ctx.update_layout(self.p_layout) 
		p_fdesc = pango.FontDescription(font)
		self.p_layout.set_font_description(p_fdesc)
		self.p_layout.set_width(int(280 * self.scale*pango.SCALE))
		self.p_layout.set_wrap(pango.WRAP_WORD)
		self.p_layout.set_alignment(pango.ALIGN_LEFT)
		self.p_layout.set_markup(value)
		ctx.set_source_rgba(r,g,b,a)
		ctx.show_layout(self.p_layout)
		ctx.restore()
	def get_text_extents(self, ctx, text, font):
	        ctx.save()
#		ctx.move_to(0,0)
		if self.p_layout == None : 
                       self.p_layout = ctx.create_layout() 
                else: 
                       ctx.update_layout(self.p_layout)
		p_fdesc = pango.FontDescription(font)
		self.p_layout.set_font_description(p_fdesc)
		self.p_layout.set_text(text)
		extents, lextents = self.p_layout.get_pixel_extents()
	        ctx.restore()
		return extents

	def reload_data (self):
		print "Üritan uuendada... ?"
		if not self.dealingWithData:
			self.dealingWithData = True
			threading.Thread(target=self.__deal_with_data).start()
			
		return True

	def __deal_with_data(self):

		__regions=[]
		__cities=[]
		usercount=0
		
		error_occurred = False
		
		print "ALGAS ANDMETEGA TEGELEMINE..."

		self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
		self.reload_menu.set_sensitive(False)
		try:
			self.__lock.acquire()

			# tallinn
			data = urlopen('http://counter.li.org/reports/place.php?place=EE%3A%3ATallinn').read()
			count_for_tallinn=self.getBetween(data, 'Linux users:</th><td>', '</td></tr>')
			print "Tallinnas: " + count_for_tallinn
	#		tallinn={
	#			'x': self.coordinate["Tallinn"][0],
	#			'y': 501-self.coordinate["Tallinn"][1],
	#			'users': int(count_for_tallinn),
	#		}

			# tartu
			data = urlopen('http://counter.li.org/reports/place.php?place=EE%3A%3ATartu').read()
			count_for_tartu=self.getBetween(data, 'Linux users:</th><td>', '</td></tr>')
			print "Tartus: " + count_for_tartu
	#		tartu={
	#			'x': self.coordinate["Tartu"][0],
	#			'y': 501-self.coordinate["Tartu"][1],
	#			'users': int(count_for_tartu),
	#		}

			exceptions = {'Tallinn': count_for_tallinn, 'Tartu': count_for_tartu}

			usercount = int(count_for_tallinn) +  int(count_for_tartu)

			# ylejäänud
			data = urlopen('http://counter.li.org/reports/place.php?place=EE').read()
			region_data=self.getBetween(data, '<!-- Subordinate places -->', '<!-- Subordinate persons -->')

	#		print region_data

			print "-------------------------"
			print "MAAKONNAD: "

			while data.find('<a href="?place=EE%3A') >= 0:
				start = data.find('<a href="?place=EE%3A')
				stop = data.find('<br>', start)   
				chunk = data[start:stop]
				__regions.append(self.extract_region(chunk, exceptions))
				data = data[stop:]

	#		print regions

			print "-------------------------"
			print "LINNAD: "

			for x in range(len(__regions)):

				usercount += int(__regions[x]["users"])

				if(len(__regions[x]["link"])<=0):
					continue
				data = urlopen('http://counter.li.org/reports/place.php' + __regions[x]["link"]).read()
	#			print 'http://counter.li.org/reports/place.php' + __regions[x]["link"]
				linna_andmed=self.getBetween(data, '<!-- Subordinate places -->', '<!-- Subordinate persons -->')


				while data.find('<a href="?place=EE%3A') >= 0:
					start = data.find('<a href="?place=EE%3A')
					stop = data.find('<br>', start)   
					chunk = data[start:stop]
					__cities.append(self.extract_city(chunk))
					data = data[stop:]

		except:
			traceback.print_exc()
			error_occurred = True
			
		finally:
			self.__lock.release()

			if not error_occurred:

				if not (self.usercount == -1 and self.usercount_before == -1):
					self.usercount_before = self.usercount

				self.usercount = usercount
				self.regions = __regions
				self.cities = __cities

				print "ASUKOHAGA KASUTAJAID KOKKU: ", self.usercount


				if self.usercount_before != -1:
					self.difference = None
					if self.usercount_before - self.usercount > 0:
						self.difference = str(self.usercount - self.usercount_before)
						self.__notifier.notify(_("The amount of registered users has decreased by %s people.") % str(abs(self.usercount - self.usercount_before)))
					elif self.usercount_before - self.usercount < 0:
						self.difference = "+" + str(self.usercount - self.usercount_before)
						self.__notifier.notify(_("The amount of registered users has increased by %s people.") % str(abs(self.usercount - self.usercount_before)))
				else:
					self.usercount_before = self.usercount

		self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))	
		self.reload_menu.set_sensitive(True)

		self.dealingWithData = False
		self.redraw_canvas()
	

	def extract_region(self, data, exceptions):

		x = len("?place=EE%3A")
		begin = data.find("?place=EE%3A") +x
		link_start = data.find('<a href="') + len('<a href="')
		location = data[begin:]
		x = len(">")
		begin = location.find(">") +x
		link = data[link_start:]
		link = link[:link.find('"')]

#		print link

		location = location[begin:]
		y = location.find('<')
		location = location[0:y]

#		print location

		x = len("</a><td align=right>")
		begin = data.find("</a><td align=right>") +x
		xxx = data[begin:]

		if (location == "Harjumaa"):
			xxx = str(int(xxx) - int(exceptions["Tallinn"]))
		elif (location == "Tartumaa"):
			xxx = str(int(xxx) - int(exceptions["Tartu"]))

		print location + ": " + xxx

		place={
		'name': location,
		'link': link,
		'x': self.coordinate[location][0],
		'y':501-self.coordinate[location][1],
		'users':xxx,
		}
		return place



	def extract_city(self, data):

		x = len("?place=EE%3A%3A")
		begin = data.find("?place=EE%3A%3A") +x
		location = data[begin:]
		x = len(">")
		begin = location.find(">") +x
		location = location[begin:]
		y = location.find('<')
		location = location[0:y]

#		print location

		x = len("</a><td align=right>")
		begin = data.find("</a><td align=right>") +x
		xxx = data[begin:]

		print location + ": " + xxx

		place={
		'name': location,
		'users':xxx,
		}
		return place

	#taken from ClearWeatherScreenlet :)
	def getBetween(self, data, first, last):
		x = len(first)
		begin = data.find(first) +x
		end = data.find(last, begin)
		return data[begin:end]
	#--------------------------------------------------

# 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__":
	import screenlets.session
	screenlets.session.create_session(LinuxEstoniaStatsScreenlet, threading=True)
