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

import gtk, pango, os, platform, ctypes, logging
from lib import wrap_label, scrollframe

def get_free_space(folder):
	if platform.system() == 'Windows':
		free_bytes = ctypes.c_ulonglong(0)
		ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(folder), None, None, ctypes.pointer(free_bytes))
		return free_bytes.value
	else:
		s = os.statvfs(folder)
		return s.f_bsize * s.f_bavail

def get_str_size(size):
	unite = "o"
	if size >= 1024:
		size /= 1024.
		unite = "Ko"
		if size >= 1024:
			size /= 1024.
			unite = "Mo"
			if size >= 1024:
				size /= 1024.
				unite = "Go"
	return str(round(size, 2)) + " " + unite

class modifications_store(gtk.ListStore):
	def __init__(self, db, apps):
		gtk.ListStore.__init__(self, gtk.gdk.Pixbuf, str)
		
		for app in apps:
			try:
				icon = gtk.gdk.pixbuf_new_from_file(app["icon"]).scale_simple(24,24,gtk.gdk.INTERP_BILINEAR)
			except glib.GError:
				icon = self.parent.render_icon(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR)
			
			try:
				version = db.get_downloads(app["appid"])[0]["version"]
				self.append([icon, "<big>" + app["parentname"] + "</big> <small>" + str(version) + "\n" + app["desc"] + " (" + get_str_size(app["zipsize"]) + ")</small>"])
			except:
				pass
				
class modifications_list(gtk.TreeView):
	def __init__(self, db, apps):
		self.store = modifications_store(db, apps)
		gtk.TreeView.__init__(self, self.store)
		self.set_headers_visible(False)
		
		cellicon = gtk.CellRendererPixbuf()
		celltext = gtk.CellRendererText()
		celltext.set_property('ellipsize', pango.ELLIPSIZE_MIDDLE)
		
		iconcolumn = gtk.TreeViewColumn('Icone', cellicon, pixbuf=0)
		textcolumn = gtk.TreeViewColumn('App', celltext, markup=1)
		
		self.append_column(iconcolumn)
		self.append_column(textcolumn)
		

class confirm_dialog(gtk.Dialog):
	def __init__(self, parent, db):
		self.db = db
		
		gtk.Dialog.__init__(self, "Appliquer les changements suivants ?", parent, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT|gtk.DIALOG_NO_SEPARATOR)
		self.set_icon_list(gtk.gdk.pixbuf_new_from_file("icons/SynApps16.png"), gtk.gdk.pixbuf_new_from_file("icons/SynApps24.png"), gtk.gdk.pixbuf_new_from_file("icons/SynApps32.png"), gtk.gdk.pixbuf_new_from_file("icons/SynApps64.png"), gtk.gdk.pixbuf_new_from_file("icons/SynApps128.png"))
		self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
		self.set_default_response(gtk.RESPONSE_CANCEL)
		
		vbox = self.get_content_area()
		self.table = gtk.Table()
		vbox.pack_start(self.table)
		
		
		self.table.set_row_spacings(5)
		self.table.set_col_spacings(5)
		
		self.table.attach(gtk.image_new_from_stock(gtk.STOCK_DIALOG_QUESTION, gtk.ICON_SIZE_DIALOG), 0, 1, 0, 2, 0, 0)
		
		label = gtk.Label()
		label.set_use_markup(True)
		label.set_markup("<big><b>Appliquer les changements suivants ?</b></big>")
		self.table.attach(label, 1, 2, 0, 1, gtk.EXPAND|gtk.FILL, gtk.FILL)
		
		label = wrap_label.WrapLabel("Cette liste récapitulative vous permet de vérifier les applications qui seront installée ou désinstallées.")

		self.table.attach(label, 1, 2, 1, 2, gtk.EXPAND|gtk.FILL, gtk.FILL)
		
		install = db.get_apps_to_install()
		update = db.get_apps_to_update()
		uninstall = db.get_apps_to_uninstall()
		
		freesize = get_free_space(self.db.get_config('appspath'))
		installsize = sum([i['size'] for i in install])
		downloadsize = sum([i['zipsize'] for i in install]) + sum([i['zipsize'] for i in update])
		uninstallsize = sum([i['size'] for i in uninstall])
		newfreesize = (freesize + uninstallsize - installsize - downloadsize)
		
		logging.debug("Espace restant : %s" % get_str_size(freesize))
		logging.debug("Taille des applications à installer : %s" % get_str_size(installsize))
		logging.debug("Taille des paquets à télécharger : %s" % get_str_size(downloadsize))
		logging.debug("Taille des applications à désinstaller : %s" % get_str_size(uninstallsize))
		logging.debug("Espace libre après les modifications : %s" % get_str_size(newfreesize))
		
		if newfreesize <= 0:
			self.add_list("Ajouter", install)
			self.add_list("Mettre à jour", update)
			self.add_list("Supprimer", uninstall)
			
			row = self.table.get_property("n-rows")
			label = gtk.Label()
			label.set_use_markup(True)
			label.set_markup("<b>Espace insuffisant : (%s manquants)</b>" % get_str_size(- newfreesize))
			self.table.attach(label, 1, 2, row, row+1, gtk.EXPAND|gtk.FILL, gtk.FILL)
		elif len(install) > 0 or len(update) > 0 or len(uninstall) > 0:
			self.add_list("Ajouter", install)
			self.add_list("Mettre à jour", update)
			self.add_list("Supprimer", uninstall)
			
			self.add_button(gtk.STOCK_APPLY, gtk.RESPONSE_OK)
		else:
			label = gtk.Label()
			label.set_use_markup(True)
			label.set_markup("<b>Aucun changement à appliquer</b>")
			self.table.attach(label, 1, 2, 2, 3, gtk.EXPAND|gtk.FILL, gtk.FILL)
		
		self.show_all()
		
	def run(self):
		response = gtk.Dialog.run(self)
		self.destroy()
		
		if response == gtk.RESPONSE_OK:
			return True
		return False
		
	def add_list(self, title, apps):
		if len(apps) > 0:
			row = self.table.get_property("n-rows")
			
			# Titre
			label = gtk.Label()
			label.set_use_markup(True)
			label.set_markup("<b>" + title + "</b>")
			label.set_alignment(0, 0.5)
			self.table.attach(label, 1, 2, row, row+1, gtk.EXPAND|gtk.FILL, gtk.FILL)
			
			# Liste
			liste = modifications_list(self.db, apps)
			
			scroll = scrollframe.scrollframe()
			scroll.set_size_request(300, 100)
			scroll.add_with_viewport(liste)
		
			self.table.attach(scroll, 1, 2, row+1, row+2, gtk.EXPAND|gtk.FILL, gtk.EXPAND|gtk.FILL)
