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

class DeleteScreen
	
	def initialize(extlayers, button)
		lang = ENV['LANGUAGE'][0..1]
		lang = ENV['LANG'][0..1] if lang.nil?
		lang = "en" if lang.nil?
		@tl = MfsTranslator.new(lang, "DeleteScreen.xml")
		@layers = Array.new
		fixed = Gtk::Fixed.new
		#### Was the deletion cancelled?
		@deletecancelled = false
		#### Table for deletion of single partitions
		@parttable = nil
		# list of drives
		@partdrives = Array.new
		# shown partitions
		@partparts = Array.new
		# headers
		@partheaders = Array.new
		# checkboxes
		@partchecks = Array.new
		# labels
		@partlabels = Array.new
		#### Table for deletion of complete drives
		@drivetable = nil
		@drivedrives = Array.new
		@drivechecks = Array.new
		@drivelabels = Array.new
		#### Progress bar for deletion
		@deleteprogress = Gtk::ProgressBar.new
		
		greentile = Gtk::EventBox.new.add Gtk::Image.new("deletelightgreennotext.png")
		orangetile = Gtk::EventBox.new.add Gtk::Image.new("deleteorange.png")
		reinsttext = TileHelpers.create_label("<b>" + @tl.get_translation("fasthead") + "</b>\n\n" + @tl.get_translation("fastbody"), 380)
		secdeltext = TileHelpers.create_label("<b>" + @tl.get_translation("fullhead") + "</b>\n\n" + @tl.get_translation("fullbody"), 380)
		
		fixed.put(orangetile, 0, 0)
		fixed.put(greentile, 0, 130)
		fixed.put(secdeltext, 130, 0)
		fixed.put(reinsttext, 130, 130) 
		
		TileHelpers.place_back(fixed, extlayers)
		
		### Layer for deletion of single partitions
		
		green2tile = Gtk::EventBox.new.add Gtk::Image.new("deletegreen.png")
		fixeddelete = Gtk::Fixed.new
		TileHelpers.place_back(fixeddelete, extlayers)
		delscroll = Gtk::ScrolledWindow.new
		delscroll.height_request = 160
		delscroll.width_request = 760
		delscroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ) 
		fixeddelete.put(green2tile, 0, 0)
		fixeddelete.put(delscroll, 130, 100)
		drivetext = TileHelpers.create_label("<b>" + @tl.get_translation("parthead") + "</b>\n\n" + @tl.get_translation("partbody"), 510)
		fixeddelete.put(drivetext, 130, 0)
		# Table for drives
		@parttable = Gtk::Table.new(2, 11, false)
		align = Gtk::Alignment.new(0, 0, 0.1, 0.1)
		align.add @parttable
		delscroll.add_with_viewport align
		# delscroll.add drivetab
		anc = @parttable.get_ancestor(Gtk::Viewport)
		anc.modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse('#00419c') )
		anc.modify_fg(Gtk::STATE_NORMAL, Gdk::Color.parse('#00419c') )
		anc.modify_text(Gtk::STATE_NORMAL, Gdk::Color.parse('#ffffff') )
		# puts anc.to_s
		# Forward button:
		text5 = Gtk::Label.new
		text5.width_request = 250
		text5.wrap = true
		text5.set_markup("<span color='white'>" + @tl.get_translation("deletenow") + "</span>")
		forw  = Gtk::EventBox.new.add Gtk::Image.new("forward.png")
		fixeddelete.put(forw, 853, 282)
		fixeddelete.put(text5, 605, 288)
		# End forward button
		forw.signal_connect('button-release-event') { |x,y|
			if y.button == 1 
				if TileHelpers.yes_no_dialog(@tl.get_translation("confirmbody"), @tl.get_translation("confirmhead"))
					extlayers.each { |k,v|v.hide_all }
					extlayers["deleteprogress"].show_all
					# run dd to delete
					run_deletion(@deleteprogress, false)
					unless @deletecancelled == true
						TileHelpers.success_dialog(@tl.get_translation("successbody"), @tl.get_translation("successhead"))
					else
						TileHelpers.success_dialog(@tl.get_translation("partialbody"), @tl.get_translation("partialhead"))
					end
					extlayers.each { |k,v|v.hide_all }
					extlayers["start"].show_all
				end
			end
		}
		
		
		### Layer for progress of deletion
		
		fixedprogress = Gtk::Fixed.new
		winetile = Gtk::EventBox.new.add Gtk::Image.new("deletegreen.png")
		fixedprogress.put(winetile, 0, 0)
		cancelbutton = TileHelpers.place_back(fixedprogress, extlayers, false)
		@deleteprogress.width_request = 510
		@deleteprogress.height_request = 32
		fixedprogress.put(@deleteprogress, 130, 120)
		progresstext = TileHelpers.create_label("<b>" + @tl.get_translation("runninghead") + "</b>\n\n" + @tl.get_translation("runningbody"), 510)
		fixedprogress.put(progresstext, 130, 0)
		
		cancelbutton.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				@deletecancelled = true
			end
		}
		
		button.signal_connect('button-release-event') { |x, y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				extlayers["deletestart"].show_all
			end
		}
		greentile.signal_connect('button-release-event') { |x,y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				@partdrives, @partparts, @partheaders, @partchecks, @partlabels = fill_part_tab(@parttable, @partheaders, @partchecks, @partlabels)
				extlayers["deletepartition"].show_all
			end
		}
		orangetile.signal_connect('button-release-event') { |x,y|
			if y.button == 1 
				extlayers.each { |k,v|v.hide_all }
				@drivedrives, @drivechecks, @drivelabels = fill_drive_tab(@drivetable, @drivechecks, @drivelabels)
				extlayers["deletedrive"].show_all
			end
		}
		
		extlayers["deletestart"] = fixed
		@layers[0] = fixed
		extlayers["deletepartition"] = fixeddelete
		@layers[1] = fixeddelete
		extlayers["deleteprogress"] = fixedprogress
		@layers[2] = fixedprogress
		
		drivelayer = create_drive_tab(extlayers)
		extlayers["deletedrive"] = drivelayer
		@layers[3] = drivelayer
		
	end
	attr_reader :layers
	
	def create_drive_tab(extlayers)
		orangetile = Gtk::EventBox.new.add Gtk::Image.new("deletegreen.png")
		fixed = Gtk::Fixed.new
		TileHelpers.place_back(fixed, extlayers)
		delscroll = Gtk::ScrolledWindow.new
		delscroll.height_request = 170
		delscroll.width_request = 760
		delscroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ) 
		fixed.put(orangetile, 0, 0)
		fixed.put(delscroll, 130, 90)
		drivetext = TileHelpers.create_label("<b>" + @tl.get_translation("parthead") + "</b>\n\n" + @tl.get_translation("drivebody"), 510)
		fixed.put(drivetext, 130, 0)
		@drivetable = Gtk::Table.new(2, 2, false)
		align = Gtk::Alignment.new(0, 0, 0.1, 0.1)
		align.add @drivetable
		delscroll.add_with_viewport align
		anc = @drivetable.get_ancestor(Gtk::Viewport)
		anc.modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse('#00419c') )
		text5 = Gtk::Label.new
		text5.width_request = 250
		text5.wrap = true
		text5.set_markup("<span color='white'>" + @tl.get_translation("deletenow") + "</span>")
		forw  = Gtk::EventBox.new.add Gtk::Image.new("forward.png")
		forw.signal_connect('button-release-event') { |x,y|
			if y.button == 1
				if TileHelpers.yes_no_dialog(@tl.get_translation("confirmbody"), @tl.get_translation("confirmhead"))
					extlayers.each { |k,v|v.hide_all }
					extlayers["deleteprogress"].show_all
					# run dd to delete
					run_deletion(@deleteprogress, true)
					unless @deletecancelled == true
						TileHelpers.success_dialog(@tl.get_translation("successbody"), @tl.get_translation("successhead"))
					else
						TileHelpers.success_dialog(@tl.get_translation("partialbody"), @tl.get_translation("partialhead"))
					end
					extlayers.each { |k,v|v.hide_all }
					extlayers["start"].show_all
				end
			end
		}
		fixed.put(forw, 853, 282)
		fixed.put(text5, 605, 288)
		return fixed
	end
	
	
	def fill_part_tab(table, oldheaders, oldchecks, oldlabels)
		TileHelpers.umount_all
		table.row_spacings = 4
		parts = Array.new
		headers = Array.new
		drives = Array.new
		checks = Array.new
		labels = Array.new
		Dir.entries("/sys/block").each { |l|
			drives.push(MfsDiskDrive.new(l, false)) if l =~ /[a-z]$/ 
		}
		oldheaders.each { |h| table.remove h }
		oldlabels.each{ |l| table.remove l } 
		oldchecks.each{ |c| table.remove c } 
		
		table.resize(drives.size * 100, 2)
		rowcount = 0
		drives.each { |d|
			label = "<b>#{d.vendor} #{d.model} - #{d.human_size} - #{d.device}"
			if d.usb == true
				label = label + " (USB)</b>\n"
			else
				label = label + " (SATA/eSATA/IDE)</b>\n"
			end
			l = TileHelpers.create_label(label, 670)
			l.height_request = 17
			headers.push l
			table.attach(l, 0, 2, rowcount, rowcount+1)
			rowcount += 1
			partcount = 0
			d.partitions.each { |p|
				unless p.fs.to_s.strip == ""
					pltext = "#{p.device} - #{p.human_size} - #{p.fs}"
					mnt, opts = p.mount_point 
					pltext = @tl.get_translation("inuse").gsub("DRIVENAME", pltext) unless mnt.nil? 
					pl = TileHelpers.create_label(pltext, 650)
					cb = Gtk::CheckButton.new
					cb.sensitive = false unless mnt.nil? 
					labels.push pl
					checks.push cb
					parts.push p.device
					table.attach(pl, 1, 2, rowcount, rowcount+1)
					table.attach(cb, 0, 1, rowcount, rowcount+1)
					rowcount += 1
					partcount += 1
				end
			}
		}
		table.resize(rowcount, 2)
		return drives, parts, headers, checks, labels
	end
	
	def fill_drive_tab(table, oldchecks, oldlabels)
		TileHelpers.umount_all
		table.row_spacings = 4
		checks = Array.new
		labels = Array.new
		drives = Array.new
		Dir.entries("/sys/block").each { |l|
			drives.push(MfsDiskDrive.new(l, false)) if l =~ /[a-z]$/ 
		}
		oldlabels.each{ |l| table.remove l } 
		oldchecks.each{ |c| table.remove c } 
		table.resize(drives.size, 2)
		rowcount = 0
		drives.each { |d|
			label = "<b>#{d.vendor} #{d.model} - #{d.human_size} - #{d.device}"
			if d.usb == true
				label = label + " (USB)"
			else
				label = label + " (SATA/eSATA/IDE)"
			end
			mnt = d.mounted 
			label = @tl.get_translation("inuse").gsub("DRIVENAME", label) if mnt == true 
			label = label + "</b>\n"
			l = TileHelpers.create_label(label, 650)
			l.height_request = 17
			labels.push l
			table.attach(l, 1, 2, rowcount, rowcount+1)
			cb = Gtk::CheckButton.new
			cb.sensitive = false if mnt == true
			checks.push cb
			table.attach(cb, 0, 1, rowcount, rowcount+1)
			rowcount += 1
		}
		return drives, checks, labels
	end
	
	# fulldisks == true means to delete whole drives
	# fulldisks == false means to delete selected partitions only
	def run_deletion(progress, fulldisks)
		@deletecancelled = false
		delete_devices = Array.new
		# start a new dd process for every 16 chunks of 4 Megabyte = 64MB per process
		chunk_size = 16
		delete_chunks = Hash.new
		if fulldisks == true
			puts "Deletion of complete disks requested"
			0.upto(@drivedrives.size - 1) { |n|
				delete_devices.push(@drivedrives[n].device) if @drivechecks[n].active?
				delete_chunks[@drivedrives[n].device] = ( @drivedrives[n].size / 64 / 1024 ** 2 ) + 1  
			}
		else
			puts "Deletion of partitions requested"
			chunk_size = 2
			0.upto(@partparts.size - 1) { |n|
				delete_devices.push(@partparts[n]) if @partchecks[n].active?
				delete_chunks[@partparts[n]] = 16
			}
		end
		puts delete_devices.join(", ") 
		delete_devices.each { |d|
			starttime = Time.now.to_i 
			0.upto(delete_chunks[d] - 1) { |n|
				if @deletecancelled == false
					seekct = n * chunk_size
					comm = "dd if=/dev/zero of=/dev/#{d} bs=4M count=#{chunk_size.to_s} seek=#{seekct.to_s}" 
					system(comm)
					system("sync")
					current_time = Time.now.to_i 
					t = @tl.get_translation("pgdel").gsub("DRIVENAME", d)
					t = t + " - " + (n * 100 / delete_chunks[d]).to_s + @tl.get_translation("pgpercent").gsub("PERCENT", "")
					progress.fraction = n.to_f / delete_chunks[d].to_f 
					delta_time = current_time - starttime
					if fulldisks == true && delta_time > 20 && n > 2
						time_per_chunk = delta_time.to_f / n.to_f
						time_remaining = ( delete_chunks[d].to_f - n.to_f ) * time_per_chunk
						minutes_remaining = ( time_remaining + 30.0 ) / 60.0 
						nice_minutes = minutes_remaining.to_i % 60
						nice_hours = minutes_remaining.to_i / 60
						if nice_hours < 1 && nice_minutes < 3
							t = t + " - " + @tl.get_translation("pgone")
						elsif nice_hours < 2
							t = t + " - " + @tl.get_translation("pgminutes").gsub("MINUTES",  minutes_remaining.to_i.to_s) 
						else
							t = t + " - " + @tl.get_translation("pgminutes").gsub("MINUTES",  nice_minutes.to_i.to_s).gsub("HOURS", nice_hours.to_i.to_s)  
						end
					end
					progress.text = t 
					while (Gtk.events_pending?)
						Gtk.main_iteration
					end
				end
			}
		}
		unless @deletecancelled == true
			progress.text = @tl.get_translation("pgdone")
			progress.fraction = 1.0
		end
	end
	
end

