#!/usr/bin/ruby
# encoding: utf-8

require 'MfsSysProfile'

class PcInspectorScreen	
	def initialize(extlayers, button, nwscreen)
		lang = ENV['LANGUAGE'][0..1]
		lang = ENV['LANG'][0..1] if lang.nil?
		lang = "en" if lang.nil?
		@lang = lang
		@tl = MfsTranslator.new(lang, "PcInspectorScreen.xml")
		@extlayers = extlayers
		@layers = Array.new
		@urllabel = Gtk::Label.new
		## table for first SMART read out
		@smarttab = nil
		@smart_quick_icons = Array.new
		@smart_quick_descriptions = Array.new
		## progressbar for SMART self test routine
		@smart_progress = nil
		@break_smart_test = nil
		## table for second SMART readout
		@smartsumtab = nil
		@smart_detail_icons = Array.new
		@smart_detail_descriptions = Array.new
		## Button and description to jump to save function
		@save_button = nil
		@save_text = nil
		## Button and progress bar for CPU burn
		@cpuburnprogress = Gtk::ProgressBar.new
		@killcpuburn = Gtk::Button.new(@tl.get_translation("killsystest"))
		# @killcpuburn.sensitive = false
		# This flag indicates cooling problems
		@cooling = false
		# Array containing messages to display
		@messages = Array.new 
		# errorlevel, can only be raised
		@errorlevel = 0 
		@trafficlight = nil
		@testcancelled = false
		@infotext = nil
		
		# WTF?
		@cpuburn_next = "winfixsmart"
		
		button1 = Gtk::EventBox.new.add Gtk::Image.new("systest1.png")
		button2 = Gtk::EventBox.new.add Gtk::Image.new("systest2.png")
		button3 = Gtk::EventBox.new.add Gtk::Image.new("systest3.png")
		back = Gtk::EventBox.new.add Gtk::Image.new("cancel.png")
		
		text1 = Gtk::Label.new
		text1.width_request = 380
		text1.wrap = true
		text1.set_markup("<span foreground='white'>" + @tl.get_translation("inspect") + "</span>")
		
		text2 = Gtk::Label.new
		text2.width_request = 380
		text2.wrap = true
		text2.set_markup("<span foreground='white'>" + @tl.get_translation("sysprofile") + "</span>")
		
		text3 = Gtk::Label.new
		text3.width_request = 380
		text3.wrap = true
		text3.set_markup("<span foreground='white'>" + @tl.get_translation("monitortest") + "</span>")
		
		text4 = Gtk::Label.new
		text4.width_request = 250
		text4.wrap = true
		text4.set_markup("<span color='white'>" + @tl.get_translation("cancel") + "</span>")
		
		fixed = Gtk::Fixed.new
		
		if @lang == "pl"
			fixed.put(button1, 0, 0)
			# fixed.put(button2, 0, 130)
			fixed.put(button3, 0, 130)
			fixed.put(back, 852, 332)
			fixed.put(text1, 130, 20)
			# fixed.put(text2, 130, 150)
			fixed.put(text3, 130, 150)
			fixed.put(text4, 605, 338)
		else
			fixed.put(button1, 0, 0)
			fixed.put(button2, 0, 130)
			fixed.put(button3, 0, 260)
			fixed.put(back, 852, 332)
			fixed.put(text1, 130, 20)
			fixed.put(text2, 130, 150)
			fixed.put(text3, 130, 280)
			fixed.put(text4, 605, 338)
		end
		
		@layers[0] = fixed
		extlayers["pcinspector"] = fixed 
		
		button.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				extlayers["pcinspector"].show_all
			end
		}
		button1.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				extlayers["pcloadtest"].show_all
				run_long_test
			end
		}
		button2.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				if File.exists?("/var/run/lesslinux/sysprofile.url")
					url = File.new("/var/run/lesslinux/sysprofile.url").read.strip
					@urllabel.set_markup("<span color='white'>" + @tl.get_translation("sysprofiledonebody").gsub("SYSPROFILEURL", url.strip) + "</span>")
					system("nohup su surfer -c \"firefox '#{url}'\" &")
					extlayers["pcsysprofiledone"].show_all
				elsif nwscreen.test_connection == false
					nwscreen.nextscreen = "pcsysprofile"
					nwscreen.fill_wlan_combo 
					# Check for networks first...
					extlayers["networks"].show_all
				else
					extlayers["pcsysprofile"].show_all
				end
			end
		}
		button3.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				system("ruby -I /usr/share/lesslinux/notfallcd4 /usr/share/lesslinux/notfallcd4/monitortest.rb &") 
			end
		}
		back.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				extlayers["start"].show_all
			end
		}
		create_sysprofile_layer
		create_sysprofile_done
		create_test_layer
		create_result_layer
		return fixed
	end
	attr_reader :layers
	
	def create_sysprofile_layer
		fixed = Gtk::Fixed.new
		back = Gtk::EventBox.new.add Gtk::Image.new("cancel.png")
		tile = Gtk::EventBox.new.add Gtk::Image.new("systestneutral.png")
		deltext = TileHelpers.create_label("<b>" + @tl.get_translation("sysprofilehead") + "</b>\n\n" + @tl.get_translation("sysprofilebody"), 510)
		text4 = Gtk::Label.new
		text4.width_request = 250
		text4.wrap = true
		text4.set_markup("<span color='white'>" + @tl.get_translation("cancel") + "</span>")
		showprivacy = Gtk::Button.new @tl.get_translation("showprivacy")
		showprivacy.width_request = 380
		showprivacy.height_request = 32
		mailentry = Gtk::Entry.new
		mailentry.width_request= 300
		maillabel = TileHelpers.create_label(@tl.get_translation("email"), 80)
		newslabel = TileHelpers.create_label(@tl.get_translation("newsletter"), 240)
		shoplabel = TileHelpers.create_label(@tl.get_translation("shopping"), 240)
		shopcheck = Gtk::CheckButton.new("")
		newscheck = Gtk::CheckButton.new("")
		fixed.put(back, 852, 332)
		fixed.put(text4, 605, 338)
		fixed.put(tile, 0, 0)
		fixed.put(deltext, 130, 0)
		fixed.put(mailentry, 210, 180)
		fixed.put(maillabel, 130, 180)
		fixed.put(newslabel, 150, 100)
		fixed.put(newscheck, 130, 100)
		fixed.put(shoplabel, 150, 140)
		fixed.put(shopcheck, 130, 140)
		fixed.put(showprivacy, 130, 220)
		@layers[1] = fixed
		@extlayers["pcsysprofile"] = fixed
		back.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				@extlayers.each { |k,v|v.hide_all }
				@extlayers["start"].show_all
			end
		}
		showprivacy.signal_connect('button-release-event') { |x, y|
			@extlayers.each { |k,v|v.hide_all }
			@extlayers["legal2"].show_all
		}
		text5 = Gtk::Label.new
		text5.width_request = 230
		text5.wrap = true
		text5.set_markup("<span color='white'>" + @tl.get_translation("createsysprofile") + "</span>")
		forw  = Gtk::EventBox.new.add Gtk::Image.new("forward.png")
		fixed.put(forw, 853, 282)
		fixed.put(text5, 605, 288)
		forw.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				@extlayers.each { |k,v|v.hide_all }
				prof = MfsSysProfile.new
				n = 0
				n = 1 if newscheck.active? == true
				h = 0
				h = 1 if shopcheck.active? == true
				begin
					url = prof.send('http://sysprofile.lesslinux.com/submit.php', mailentry.text.strip, n, h) 
					$stderr.puts url
					u = File.new("/var/run/lesslinux/sysprofile.url", "w")
					u.write url
					u.close 
					system("nohup su surfer -c \"firefox '#{url}'\" &")
					@urllabel.set_markup("<span color='white'>" + @tl.get_translation("sysprofiledonebody").gsub("SYSPROFILEURL", url.strip) + "</span>")
				rescue
					system("rm /var/run/lesslinux/sysprofile.url")
					@urllabel.set_markup("<span color='white'>" + @tl.get_translation("sysprofilefailedbody") + "</span>")
				end
				@extlayers["pcsysprofiledone"].show_all
			end
		}
	end
	
	def create_sysprofile_done
		fixed = Gtk::Fixed.new
		back = Gtk::EventBox.new.add Gtk::Image.new("cancel.png")
		tile = Gtk::EventBox.new.add Gtk::Image.new("systestneutral.png")
		# deltext = TileHelpers.create_label("<b>" + @tl.get_translation("sysprofiledonehead") + "</b>\n\n" + @tl.get_translation("sysprofiledonebody"), 510)
		text4 = Gtk::Label.new
		text4.width_request = 250
		text4.wrap = true
		text4.set_markup("<span color='white'>" + @tl.get_translation("cancel") + "</span>")
		fixed.put(back, 852, 332)
		fixed.put(text4, 605, 338)
		@urllabel.width_request = 510
		@urllabel.wrap = true
		fixed.put(@urllabel, 130, 0)
		back.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				@extlayers.each { |k,v|v.hide_all }
				@extlayers["start"].show_all
			end
		}
		@layers[4] = fixed
		@extlayers["pcsysprofiledone"] = fixed
	end
	
	def create_test_layer
		fixed = Gtk::Fixed.new
		tile = Gtk::EventBox.new.add Gtk::Image.new("systestgreen.png")
		deltext = TileHelpers.create_label("<b>" + @tl.get_translation("systesthead") + "</b>\n\n" + @tl.get_translation("systestbody"), 510)
		@cpuburnprogress.width_request = 380
		@cpuburnprogress.height_request = 32
		@killcpuburn.width_request = 120
		@killcpuburn.height_request = 32
		fixed.put(tile, 0, 0)
		fixed.put(deltext, 130, 0)
		fixed.put(@cpuburnprogress, 130, 108)
		fixed.put(@killcpuburn, 515, 108)
		@killcpuburn.signal_connect("clicked") {
			system("killall -9 cpuburn") 
			@testcancelled = true 
			@killcpuburn.sensitive = false
			# @extlayers.each { |k,v|v.hide_all }
			# @extlayers["pcsystestres"].show_all
		}
		back = Gtk::EventBox.new.add Gtk::Image.new("cancel.png")
		text4 = Gtk::Label.new
		text4.width_request = 250
		text4.wrap = true
		text4.set_markup("<span color='white'>" + @tl.get_translation("cancel") + "</span>")
		fixed.put(back, 852, 332)
		fixed.put(text4, 605, 338)
		@layers[2] = fixed
		@extlayers["pcloadtest"] = fixed
		# FIXME: 
		@cpuburnprogress.text = @tl.get_translation("systesthead")
		@cpuburnprogress.pulse
		back.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				@extlayers.each { |k,v|v.hide_all }
				@extlayers["start"].show_all
			end
		}
	end
	
	def create_result_layer
		fixed = Gtk::Fixed.new
		# @trafficlight = Gtk::Image.new("systestneutral.png")
		@trafficlights = [  
			Gtk::Image.new("ampel1gruen.png"),
			Gtk::Image.new("ampel2gelb.png"),
			Gtk::Image.new("ampel3rot.png")
		]
		# tile = Gtk::EventBox.new.add @trafficlight
		@infotext = TileHelpers.create_label("<b>" + @tl.get_translation("sysreshead") + "</b>\n\n" + @tl.get_translation("sysresbody"), 510)
		@detailtext = TileHelpers.create_label("", 450) 
		text4 = Gtk::Label.new
		text4.width_request = 250
		text4.wrap = true
		text4.set_markup("<span color='white'>" + @tl.get_translation("normalback") + "</span>")
		back = Gtk::EventBox.new.add Gtk::Image.new("cancel.png")
		fixed.put(back, 852, 332)
		fixed.put(text4, 605, 338)
		@trafficlights.each { |t|  fixed.put(t, 0, 0) }
		# fixed.put(tile, 0, 0)
		fixed.put(@infotext, 130, 0)
		fixed.put(@detailtext, 160, 75)
		back.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				@extlayers.each { |k,v|v.hide_all }
				@extlayers["start"].show_all
			end
		}
		@layers[3] = fixed
		@extlayers["pcsystestres"] = fixed
		fixed.signal_connect('show') {
			@trafficlights.each { |t| t.hide_all }
			# Now properly format the next screen
			if @messages.size < 1
				@trafficlights[0].show_all
				@infotext.set_markup("<span color='white'>" + @tl.get_translation("result1") + "</span>")
				@detailtext.set_markup("<span color='white'></span>")
			elsif @errorlevel > 0
				@trafficlights[2].show_all
				@infotext.set_markup("<span color='white'>" + @tl.get_translation("result1") + "</span>")
				@detailtext.set_markup("<span color='white'>" + @messages.join("\n\n") + "</span>")
			else
				@trafficlights[1].show_all
				@infotext.set_markup("<span color='white'>" + @tl.get_translation("result1") + "</span>")
				@detailtext.set_markup("<span color='white'>" + @messages.join("\n\n") + "</span>")
			end
			while (Gtk.events_pending?)
				Gtk.main_iteration
			end
		}
	end
	
	def run_long_test
		# Run time is set to the longest runtime found, minimum run time ist five minutes for cpuburn
		# or zero minutes if no sensors are found
		runtime = 0.0 
		cpuburntime = 300
		totaltime = 0
		sensors_found = false
		# this flag indicates cooling problems
		@cooling = false
		@messages = Array.new
		@errorlevel = 0
		@testcancelled = false
		@killcpuburn.sensitive = true
		IO.popen("sensors") { |line|
			while line.gets
				sensors_found = true if $_ =~ /cpu temperature.*?\+(\d+)\.\d°C.*?crit.*?(\d+)\.\d°C/i 
				sensors_found = true if $_ =~ /temp\d.*?\+(\d+)\.\d°C.*?crit.*?(\d+)\.\d°C/i 	
				sensors_found = true if $_ =~ /temp\d.*?\+(\d+)\.\d°C.*?high.*?(\d+)\.\d°C/i 
			end
		}
		if sensors_found == false
			TileHelpers.error_dialog(@tl.get_translation("nosensorbody"), @tl.get_translation("nosensorhead"))
			cpuburntime = 30
		end
		totaltime = cpuburntime 
		# Now, identify any hard disk and run a long test on it
		auxdrives = Array.new
		Dir.entries("/sys/block").each { |l|
			auxdrives.push(MfsDiskDrive.new(l, false)) if l =~ /[a-z]$/ || l =~ /mmcblk[0-9]$/ ||  l =~ /mmcblk[0-9][0-9]$/
		}
		auxdrives.each { |d|
			disktime = d.smart_long_test.to_i * 63
			totaltime = disktime if disktime > totaltime
		}
		totaltime += cpuburntime 
		totaltime = 300 if File.exists?("/tmp/debug_pcinspection") 
		# Now run with consistent updated progress bar...
		system("cpuburn &") 
		ccount = 0
		while ( runtime < totaltime.to_f && @testcancelled == false )  
			if ccount % 10 == 0
				@cpuburnprogress.fraction = runtime / totaltime.to_f 
				@cpuburnprogress.text = @tl.get_translation("minutesremaining").gsub("MINUTES", (( totaltime.to_f - runtime.to_f) / 60.0 ).to_i.to_s)
				if runtime > cpuburntime.to_f
					system("killall -9 cpuburn") 
				end
				if ccount % 50 == 0
					cputemp, critical = read_temp
					if critical - cputemp < 6
						@cooling = true
						@messages.push(@tl.get_translation("detail1"))
					end
				end
			end
			while (Gtk.events_pending?)
				Gtk.main_iteration
			end
			ccount += 1
			runtime += 0.2 
			sleep 0.2
		end
		# On cancel, just kill CPU burn and switch to the next screen
		# the running SMART test is usually aborted upon the next SMART command
		# if not, it might still provide some helpful information
		system("killall -9 cpuburn") 
		@cpuburnprogress.fraction = 1.0
		@cpuburnprogress.text = @tl.get_translation("testdone")
		# Read the smart values:
		auxdrives.each { |d|
			smart_support, smart_info, smart_error = d.error_log
			smart_test_types, smart_test_results, smart_bad_sectors, smart_reallocated, smart_seek_error = d.smart_details
			if smart_bad_sectors.to_i > 0 || smart_reallocated.to_i > 0 || smart_seek_error.to_i > 0
				@errorlevel = 1
				@messages.push(@tl.get_translation("detail2").gsub("VENDOR", d.vendor).gsub("MODEL", d.model).gsub("SIZE", d.human_size))
			elsif smart_error.size > 0 
				@messages.push(@tl.get_translation("detail3").gsub("VENDOR", d.vendor).gsub("MODEL", d.model).gsub("SIZE", d.human_size))
			end
		}
		@extlayers.each { |k,v|v.hide_all }
		@extlayers["pcsystestres"].show_all
	end
	
	def read_temp(kill=true)
		cputemp = 0
		critical = 80
		lcount = 0
		cpuline = -1
		IO.popen("sensors") { |line|
			while line.gets 
				# CPU Temperature:    +49.0°C  (high = +60.0°C, crit = +95.0°C)
				# temp1: +70.0°C (crit = +92.0°C)
				# 
				# temp1: +44.8°C (high = +70.0°C)
				#                (crit = +100.0°C, hyst = +97.0°C) 
				if $_ =~ /cpu temperature.*?\+(\d+)\.\d°C.*?crit.*?(\d+)\.\d°C/i 
					puts "Core: " + $1
					puts "Crit: " + $2
					cputemp = $1.to_i 
					critical = $2.to_i 
				elsif $_ =~ /^temp\d.*?\+(\d+)\.\d°C.*?crit.*?(\d+)\.\d°C/i 	
					puts "Core: " + $1
					puts "Crit: " + $2
					cputemp = $1.to_i 
					critical = $2.to_i
				elsif $_ =~ /^temp\d.*?\+(\d+)\.\d°C.*?high.*?(\d+)\.\d°C/i 
					puts "Core: " + $1
					puts "High: " + $2
					cpuline = lcount
					cputemp = $1.to_i
				elsif  lcount - cpuline == 1 
					puts $_
					if $_ =~ /^\s*\(.*?crit.*?(\d+)\.\d°C/i 
						puts "Crit: " + $1
						critical = $1.to_i
					end
				end
				lcount += 1
			end
			if critical - cputemp < 6 && kill == true
				system("killall -9 cpuburn")
				TileHelpers.error_dialog(@tl.get_translation("toohotbody"), @tl.get_translation("toohothead"))
			end
		}
		return cputemp, critical
	end
	
end
