#!/usr/bin/python

import os
import os.path
import string
import gtk
import gtk.glade
import gnome.ui
import gnomecanvas
import gobject

from gtk import RcStyle
from gtk import Settings

from hwdb_client import Constants

class Collector:
    def __init__(self):
    	self.output = []
    	self.comments = []
	self.devdata = []
	self.devicename = ''
    	self.i = 3638089728
	self.wTree=gtk.glade.XML (Constants.DATADIR + "/collector.glade")
	self.xmlfile = Constants.DATADIR + "/questions_en.xml"
	self.step = 0
	self.headericon = ''
	self.headtxt = ''
	self.cont_txt = ''
	self.hline = ''
	self.yesno = ''
	self.comtxt = ''
	self.comwin = ''
	self.comrtf = ''
	self.box1 = ''
	self.donetxt = ''
	self.radio = ''
	self.cont_rec = ''
	self.yesbutt = gtk.RadioButton(None, 'Yes')
	self.redo = gtk.Button()
	self.urlbutt = gtk.Button()
	self.cpybutt = gtk.Button()
	self.co_textview = gtk.TextView()
	hwdb_lock = ""
	home_path=os.environ["HOME"]	
	path = home_path+'/.hwdb'
	clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)

	if os.path.isfile(path):
	    lock = open(path)
	    hwdb_lock = lock.read()

	canvas = self.wTree.get_widget("canvas")
	self.root = canvas.root().add(gnomecanvas.CanvasGroup)
	canvas_bg = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/canvas_bg.png") 

	self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = canvas_bg, 
		 x = 0, y = 0, anchor = "nw")

	cancel = self.wTree.get_widget("cancel_button")
	self.advance = self.wTree.get_widget("adv_button")
	help = self.wTree.get_widget("help_button")

	if hwdb_lock:
  	    tt = gtk.Tooltips()
	    self.advance.hide()
	    urlbox1 = gtk.HBox(False, 0)
    	    image = gtk.Image()
    	    image.set_from_stock(gtk.STOCK_CONNECT, gtk.ICON_SIZE_BUTTON)
    	    label = gtk.Label('Show online record')
    	    urlbox1.add(image)
    	    urlbox1.add(label)
	    self.online_button = self.root.add(gnomecanvas.CanvasWidget, x = 250, y = 200, widget = self.urlbutt, 
			 width = 160, height = 30)
   	    self.urlbutt.add(urlbox1)
	    self.urlbutt.show_all()
	    cpybox1 = gtk.HBox(False, 0)
    	    image = gtk.Image()
    	    image.set_from_stock(gtk.STOCK_COPY, gtk.ICON_SIZE_BUTTON)
    	    label = gtk.Label('Copy to clipboard')
    	    cpybox1.add(image)
    	    cpybox1.add(label)
	    self.copy_button = self.root.add(gnomecanvas.CanvasWidget, x = 80, y = 200, widget = self.cpybutt, 
			 width = 160, height = 30)
   	    self.cpybutt.add(cpybox1)
	    self.cpybutt.show_all()

	    self.urlbutt.connect("clicked", lambda w: self.open_online(hwdb_lock))
	    self.cpybutt.connect("clicked", lambda w: clip.set_text(hwdb_lock))
	    tt.set_tip(self.urlbutt, 'Click here to open a browser with your record on the database server', '')
	    tt.set_tip(self.cpybutt, 'Click here to copy the id to the Gnome clipboard', '')

	    logo_img = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/hwdb.png") 
	    logo = (self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = logo_img, 
	 				x = 50, y = 45, anchor = "nw"))
	    line = self.root.add(gnomecanvas.CanvasLine,
				points = [40,85, 400, 85],
				width_pixels = 1, 
				fill_color_rgba = 288581136)

	    self.donetxt = self.root.add(gnomecanvas.CanvasText, 
			markup = '<span size="12000"><b>Submission id:</b>\n'+hwdb_lock+'</span>\n\
				\n<span size="8500" color="#000000">Attach this id to your bugreports or use it \nif you get online support.\nUse the "Copy to clipboard" button to copy and \npaste the id or the "Show online record" button to \naccess your online datasheet directly.</span>', 
			fill_color_rgba = 288581375, x = 250, y = 105)

	    self.advance.set_sensitive(False)
	else:
            self.inittext = self.root.add(gnomecanvas.CanvasText, markup = Constants.COL_TXT1,
	    				size = 8000, fill_color_rgba = self.i, x = 220, y = 140)
	    self.fadein(self.inittext)
					
	self.win = self.wTree.get_widget("window")
	self.win.set_resizable(False)
	self.win.set_size_request(450,400)
	self.win.set_icon_from_file(Constants.DATADIR + "/ubuntu_logo.png")
	
	#self.advance.grab_focus()

	help.connect("clicked", lambda w: gnome.help_display_uri ('ghelp:///usr/share/gnome/help/hwdb-client/C/hwdb-client.xml'))
	cancel.connect("clicked", lambda w: gtk.main_quit())
	self.win.connect("destroy", lambda w: gtk.main_quit())
	self.advance.connect("clicked", lambda w: self.adv(self.xmlfile))
    
    def main(self):
            gtk.main()

    def open_online(self, id):
	gnome.url_show ('http://hwdb.ubuntu.com/?xml='+id)
	gobject.timeout_add(1000, lambda: gtk.main_quit())

    def test(self, set):
	self.netani = [] 
	spk_ani = gtk.gdk.PixbufAnimation(Constants.DATADIR + "/speaker_shadow.gif") 
	spk_img = gtk.image_new_from_animation(spk_ani)

	yes_img = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/yes.png") 
	no_img = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/no.png") 
	self.anibox = gtk.VBox(False, 0)
	self.anibox.add(spk_img)
	self.anibox.show_all()

        if set[1].startswith("Audio"):
		gnome.sound_init("localhost")
		gnome.sound_play(Constants.DATADIR + "/sound.wav")
		devname = os.popen('cat /proc/asound/card0/id')
		for line in devname:
			self.devicename = line.strip()
			set[2] = "Testing detected soundcard: "+self.devicename+"\n"+set[2]
			if len(self.devdata) < 1:
		            self.devdata.append(self.devicename)
		self.canvasani = self.root.add(gnomecanvas.CanvasWidget, x = 40, y = 130, widget = self.anibox, 
			 width = 145, height = 160)
		if not (self.redo.flags() & gtk.MAPPED):
			self.repeat(set)
			self.draw_content(set)
		self.redo.set_sensitive(False)
		gobject.timeout_add(1700, lambda: self.killani(set[1]))
		gobject.timeout_add(1800, lambda: self.draw_yesno(set[1]))
	
  	if set[1].startswith("Network") or set[1].startswith("Wireless"):
		repflag = 0
		netdevice = self.getroute()[len(self.getroute())-1].strip()
		if not (self.redo.flags() & gtk.MAPPED):
			self.repeat(set)
			set[2] = set[2]+" On interface: "+netdevice
			self.draw_content(set)
		else:
			repflag = 1

		self.redo.set_sensitive(False)
		command = 'LC_ALL=C fping '+self.getroute()[9]+' 2>/dev/null'
	 	seq = 0	
		flag = 0
		while (seq < 4):
		    	while gtk.events_pending():
			        gtk.main_iteration(True)
			img = yes_img
			timer = 0
			for line in os.popen(command):
				fields = string.splitfields(line, 'is')
			status = fields[1].strip()
			if status.startswith('unreachable'):
				img = no_img
				timer = 1
				flag = flag +1
			if timer == 0:
				i=0
				while i<500000:
					i = i + 1
			if seq == 3:
				self.output.append(flag)
				self.comments.append(netdevice+" failures: "+str(flag))
				self.killnettest(set)
		    		self.devdata.append(netdevice)
				break
			gnome.sound_init("localhost")
			self.netani.append(self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = img, 
	 				x = 50+(seq*130), y = 140, anchor = "nw"))
			gnome.sound_play(Constants.DATADIR + "/ping.wav")
			seq = seq+1
		return

    def getroute(self):
	for line in os.popen('route -n'):
		if line.startswith('0.0.0.0'):
			route = string.splitfields(line, ' ')
	return route

    def get_xorgdata(self):
    	ati_brain_damage = []
        command = 'xrandr -q'
	for item in os.popen('lsmod|grep fglrx'):
	    ati_brain_damage.append(item)
	if len(ati_brain_damage):
	    retval = "\nDetected settings: impossible with fglrx"
	else:
        	for line in os.popen(command):
        		fields = string.splitfields(line, '  ')
        		if fields[0].startswith('*'):
        			freq = fields[4].strip('*')
        			if fields[4].strip('*') == '\n':
        			    freq = "N/A"
        			retval = "\nDetected settings: "+fields[1]+" @ "+freq+" Hz"
        		    	self.devdata.append(fields[1].lstrip()+" @ "+fields[4].strip('*')+" Hz")
	return retval
	
    def killani(self, set):
	self.redo.set_sensitive(True)
    	self.canvasani.destroy()
	return False
   
    def repeat(self, set):
    	repbox1 = gtk.HBox(False, 0)
	image = gtk.Image()
	image.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
	label = gtk.Label('Test again')
	repbox1.add(image)
	repbox1.add(label)
	self.redo.add(repbox1)
	self.redobutt = self.root.add(gnomecanvas.CanvasWidget, x = 330, y = 80, widget = self.redo, 
			 width = 100, height = 30)
	self.redo.show_all()

	self.redo.connect("clicked", lambda w: self.retest(set))

    def retest(self, set):
	if set[1].startswith('Network') and (self.donetxt.flags() & gtk.MAPPED):
		self.donetxt.destroy()
	        self.output.pop()
	        self.comments.pop()
	else:
    		self.yesno_hide()
	gnome.sound_init("localhost")
	self.test(set)

    def killnettest(self, set):
    	i=0
    	while (i<3):
    		self.netani[i].destroy()
		i=i+1
	self.donetxt = self.root.add(gnomecanvas.CanvasText, 
			markup = "<span size='16000'><b>Test done, please proceed</b></span>", 
			fill_color_rgba = 288581375, x = 230, y = 182)
	self.redo.set_sensitive(True)
	self.advance.set_sensitive(True)
	#self.advance.grab_focus()
	return False 

    def yesno_hide(self):
	if self.yesno:
		buffer = self.textview.get_buffer()
		self.comments.append(buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter()))
		if self.yesbutt.get_active():
			self.output.append(0)
		elif  self.partbutt.get_active():
			self.output.append(1)
		elif self.nobutt.get_active():
			self.output.append(2)
		else:
		  	self.output.append(3)
		self.yesno.destroy()
		self.comtxt.destroy()
		self.comwin.destroy()
		self.combg.destroy()
		
    def draw_yesno(self, set):
  	tt = gtk.Tooltips()
	i_out = gtk.Image()
	if self.yesno:
		self.yesno.destroy()
		self.box1.destroy()
		self.comtxt.destroy()
		self.combg.destroy()

	self.yesbutt = gtk.RadioButton(None, 'Yes')
	self.yesbutt.connect("clicked", lambda w: i_out.set_from_file(Constants.DATADIR + "/true.png"))
	self.nobutt = gtk.RadioButton(self.yesbutt, 'No')
	self.nobutt.connect("clicked", lambda w: i_out.set_from_file(Constants.DATADIR + "/false.png"))
	self.partbutt = gtk.RadioButton(self.yesbutt, 'Partial')
	self.partbutt.connect("clicked", lambda w: i_out.set_from_file(Constants.DATADIR + "/partial.png"))
	self.neutbutt = gtk.RadioButton(self.yesbutt, 'N/A')
	self.neutbutt.connect("clicked", lambda w: i_out.set_from_file(Constants.DATADIR + "/neutral.png"))

	self.yesbutt.connect("toggled", lambda w: self.advance.set_sensitive(True))
	self.nobutt.connect("toggled", lambda w: self.advance.set_sensitive(True))
	self.partbutt.connect("toggled", lambda w: self.advance.set_sensitive(False))
	self.neutbutt.connect("toggled", lambda w: self.advance.set_sensitive(True))

	commentwin = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/comment_bg.png") 
	i_out.set_from_file(Constants.DATADIR + "/true.png")

	self.box1 = gtk.VBox(False, 0)
	self.hbox1 = gtk.HBox(False, 0)
	self.box1.pack_start(self.yesbutt, False, False, 2)
	self.box1.pack_start(self.partbutt, False, False, 2)
	self.box1.pack_start(self.nobutt, False, False, 2)
	self.box1.pack_start(self.neutbutt, False, False, 2)

	self.hbox1.pack_start(i_out, False, False, 10)
	self.hbox1.pack_start(self.box1, False, False, 0)
	self.hbox1.show_all()

    	self.yesno = self.root.add(gnomecanvas.CanvasWidget, x = 40, y = 160, widget = self.hbox1, 
				width = 140, height = 100) 
	self.comtxt = self.root.add(gnomecanvas.CanvasText, 
			markup = "<span size='10000'><b>Comments:</b></span>", 
			fill_color_rgba = 288581375, x = 225, y = 135)
	self.combg = (self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = commentwin, 
	 				x = 175, y = 140, anchor = "nw"))
	self.comwin = gtk.ScrolledWindow(None, None)
	self.comwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
	self.textview = gtk.TextView()
	self.textview.set_editable(True)
	self.textview.set_cursor_visible(True)
	self.textview.set_wrap_mode(gtk.WRAP_WORD)
	self.comwin.add(self.textview)
	self.comwin.show_all()
	
	buffer = self.textview.get_buffer()
	buffer.connect("changed", lambda w: self.buffoc(buffer))

    	self.comrtf = self.root.add(gnomecanvas.CanvasWidget, x = 185, y = 150, widget = self.comwin, 
				width = 220, height = 120) 
	
	tt.set_tip(self.yesbutt, 'The device was automatically detected and is functioning properly', '')
	tt.set_tip(self.nobutt, 'The device is not functioning at all', '')
	tt.set_tip(self.partbutt, 'The device is functioning, but not fully, or it required manual configuration (please explain in comment)', '')
	tt.set_tip(self.neutbutt, 'The device is not available', '')
	tt.enable()

	self.advance.set_sensitive(True)
	#self.advance.grab_focus()
   
    def buffoc(self, buffer):
    	if buffer.get_char_count() and self.partbutt.get_active(): 
		self.advance.set_sensitive(True)
	elif self.yesbutt.get_active() or self.nobutt.get_active() or self.neutbutt.get_active():
		self.advance.set_sensitive(True)
	else:
		self.advance.set_sensitive(False)

    def draw_commentwin(self):
	self.advance.set_sensitive(True)
	scrwin = gtk.ScrolledWindow(None, None)
	scrwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
	self.co_textview.set_editable(True)
	self.co_textview.set_cursor_visible(True)
	self.co_textview.set_wrap_mode(gtk.WRAP_WORD)
	scrwin.add(self.co_textview)
	scrwin.show_all()

	c_win = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/full_comment_bg.png") 
	self.cont_rec = (self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = c_win, 
	 				x = 80, y = 120, anchor = "nw"))

    	self.cont_inp = self.root.add(gnomecanvas.CanvasWidget, x = 95, y = 130, widget = scrwin, 
				width = 265, height = 150) 

	#self.advance.grab_focus()

    def draw_content(self, set):
	if self.cont_txt:
		self.cont_txt.hide()
	if self.hline:
		self.hline.hide()
	gtk.rc_parse_string('gtk_font_name = "Sans 8"')
	self.cont_txt = self.root.add(gnomecanvas.CanvasRichText, x = 30, y = 80, width = 300, height = 180, 
				text = set[2], cursor_visible = False, grow_height = True) 
	self.hline = self.root.add(gnomecanvas.CanvasLine,
				points = [30,120, 430, 120],
				width_pixels = 1, 
				fill_color_rgba = 288581136)
	gtk.rc_reset_styles(gtk.settings_get_default())
    
    def draw_header(self, set):
	if self.headtxt:
		self.fadeout(self.headtxt)
	if self.headericon:
		self.headericon.hide()

	icon_pixbuf = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/"+set[0]) 
	head_pixbuf = gtk.gdk.pixbuf_new_from_file(Constants.DATADIR + "/header_bg.png") 

	self.headerbg = self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = head_pixbuf, 
		 x = 24, y = 26, anchor = "nw")
	self.headtxt = self.root.add(gnomecanvas.CanvasText, markup = "<span size='20000'><b>"+set[1]+"</b></span>", 
				fill_color_rgba = 288581375, x = 230, y = 42)
	self.headericon = self.root.add(gnomecanvas.CanvasPixbuf, pixbuf = icon_pixbuf, 
		 x = 40, y = 15, anchor = "nw")
    	
    def propstrip(self, line, type):
    	    line = line.rstrip("</property>\n")
	    line = line.lstrip("<property name="+type+">")
	    return line

    def fadein(self, text):
	    self.i = self.i-538976288
    	    while self.i > 0:
	    	while gtk.events_pending():
		        gtk.main_iteration(1)
	        if self.i <= 0:
		    self.i = 0
                text.set(fill_color_rgba = self.i)   
	        self.i = self.i-353703189
	    return 1

    def fadeout(self, text):
	    self.i = 1
	    while self.i <= 4294967040:
	        while gtk.events_pending():
	                gtk.main_iteration(1)
                text.set(fill_color_rgba = self.i)   
	        self.i = self.i+623191333
	    text.hide()
	    return 1

    def assemble(self):
    	self.datapipe = []
    	self.pbar = gtk.ProgressBar()
    	self.as_bar = self.root.add(gnomecanvas.CanvasWidget, x = 60, y = 175, widget = self.pbar, 
				width = 350, height = 24) 

	self.pbar.show()

	self.timer = gobject.timeout_add (100, lambda w: self.pulsator(), self)
	while gtk.events_pending():
	        gtk.main_iteration(True)

	for line in os.popen('/usr/bin/hwdb-xml -a'):
		self.datapipe.append(line)
		while gtk.events_pending():
		        gtk.main_iteration(True)
	
	self.datapipe.append("<!--<quadata>\n")
	i = 0
	for line in open(self.xmlfile, 'r'):
		line = line.strip()
		if line.startswith("<property name=title>"):
			line = self.propstrip(line, 'title')
			if not line.startswith("Assembling"):
				line = line.rstrip()
				self.datapipe.append("<question id=\""+line.lower()+"\">\n")
				if not line.startswith("Comments"):
					self.datapipe.append(" <result>"+str(self.output[i])+"</result>\n")
		    			self.datapipe.append("  <detected>"+str(self.devdata[i])+"</detected>\n")
				self.datapipe.append(" <comment>"+str(self.comments[i])+"</comment>\n")
				self.datapipe.append("</question>\n")
				i = i + 1
	self.datapipe.append("</quadata>\n-->\n")

	while gtk.events_pending():
	        gtk.main_iteration(True)

	self.timeout = gobject.timeout_add (5000, lambda w: self.hidepulse(), self)
	
    def pulsator(self):
	self.pbar.pulse()
	return True

    def hidepulse(self):

	#####################################################
	# call hwdb-send here (print to tmpfile)	    #
	#####################################################

 	self.pbar.hide()
	self.donetxt = self.root.add(gnomecanvas.CanvasText, 
			markup = "<span size='16000'><b>Thank you for your contribution</b></span>", 
			fill_color_rgba = 288581375, x = 230, y = 182)

	sendpipe = open('/tmp/hwdb_data.xml', 'w')

	for line in self.datapipe:
	    while gtk.events_pending():
		gtk.main_iteration(True)
	    sendpipe.write(line)
	sendpipe.close()
	os.spawnl(os.P_NOWAIT, '/usr/bin/hwdb-send')

	gtk.main_quit()
	return False

    def adv(self, xmlfile):
    	elem = 0
	set = []
  
	self.advance.set_sensitive(False)
	self.fadeout(self.inittext)

	if (self.yesbutt.flags() & gtk.MAPPED):
		self.yesno_hide()

	if (self.redo.flags() & gtk.MAPPED):
		self.redo.destroy()
	
	if (self.co_textview.flags() & gtk.MAPPED):
		buffer = self.co_textview.get_buffer()
		self.comments.append(buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter()))
		self.cont_rec.destroy()
		self.cont_inp.destroy()
	
	self.step = self.step + 1
	for line in open(xmlfile, 'r'):
		line = line.strip()
		if line.startswith("<advmark step="+str(self.step)+" "):
			elem = 1
			newline = line.rsplit("=", 1)
			showline = newline[1].strip('\">\n')
			set.append(showline+".png")
		if elem == 1:
			if line.startswith("<property name=title>"):
				line = self.propstrip(line, 'title')
				set.append(line.strip())
			if line.startswith("<property name=content>"):
				line = self.propstrip(line, 'content')
				set.append(line.strip())
		if line.startswith("</advmark>"):
			elem = 0
			
	if len(set) >= 1:
		self.draw_header(set)
		if self.donetxt:
			self.donetxt.hide()
		if not set[1].startswith("Comments") and \
			not set[1].endswith("test") and \
			not set[1].startswith("Video") and \
			not set[1].startswith("Assembling"):
		    self.devdata.append('null')
		    self.draw_content(set)
		    self.draw_yesno(set)
		elif set[1].startswith("Video"):
		    set[2] = set[2]+self.get_xorgdata()
		    self.draw_content(set)
		    self.draw_yesno(set)
		elif set[1].endswith("test"):
		    self.test(set)
		elif set[1].startswith("Assembling"):
		    self.draw_content(set)
		    self.assemble()
		else:
		    self.draw_content(set)
		    self.draw_commentwin()
		    self.devdata.append('null')

if __name__ == "__main__":
    base = Collector()
    base.main()
