# encoding: utf-8

#-----------------------------------------------------------
# Rumix GUI Uninstaller
#
# Author:   Dice
# License:  NYSL 0.9982 (http://www.kmonos.net/nysl/)
# URL:      http://ruby.morphball.net/rumix/
#-----------------------------------------------------------

$LOAD_PATH.unshift 'lib'
require 'pathname'

require 'rumix/wx'


begin
	module Rumix
		module Widget
			class DetailDialog < Wx::Dialog
				def initialize(parent)
					super(parent, :title => '削除されるファイル', :style => (Wx::DEFAULT_DIALOG_STYLE | Wx::RESIZE_BORDER))
					top_sizer = nil
					button = nil
					list = nil
					text = nil
					
					construct_children do |dialog|
						top_sizer = vbox_sizer do
							expand
							border MAIN_SIZER_BORDER
							
							proportion 1
							list = widget Wx::ListBox, :size => Wx::Size.new(560, 300), :name => 'detail_list', :style => Wx::LB_ALWAYS_SB|Wx::LB_HSCROLL
							
							proportion 0
							text = widget Wx::StaticText, :name => 'detail_label', :label => ''
							hbox_sizer do
								stretch_spacer(1)
								button = widget Wx::Button, :label => '閉じる'
								stretch_spacer(1)
							end
						end
					end
					
					evt_button(button, :on_stop)
					
					set_sizer(top_sizer)
					top_sizer.set_size_hints(self)
					
					#dir_path = Rumix::Registry.load.install_path.gsub("\\", "/")
					found = 0
					
					Wx::Timer.after(100) do
						app = Wx.get_app
						start = Time.now.to_f
					
						Rumix.delete_directory_recursively([Rumix.base_dir, Rumix.start_menu_dir_path], false){|event, path|
							case event
							when :directory, :file
								path.gsub!(/\\/, '/')
								list.append Uconv.sjistou8(path)
								found += 1
								
								if found % 32 == 0 then
									text.label = "探索中... (#{found} ファイル)"
								end
								
							end
							app.dispatch while app.pending
						}
						
						text.label = "探索完了 (#{found} ファイル)"
					end

				end
				
				def on_stop
					Rumix.stop_running_thread
					self.hide
				end
			end
			
			class Wizard < Wx::Wizard
			
				def initialize(*args)
					super
					
					pages = []
					#registry = Rumix::Registry.load
					#config = Rumix::Config.new.load_ini_file('rumix.ini')
	
					
					construct_children do |wizard|
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								border MAIN_SIZER_BORDER
								widget TitleText, :label => 'Rumix アンインストール'
								widget Wx::StaticText, :label => "Rumix #{Rumix::VERSION} をアンインストールします。\nこのアンインストールにより、以下のものが削除されます。"
	
								expand
								
								list = widget(Wx::ListBox)
								$list = list
								list.append "#{Rumix.base_dir} 以下の全てのファイル"
								list.append 'Windowsスタートメニューの「Rumix」グループ'
								
								widget Wx::StaticText, :label => "注：PATH環境変数やレジストリは削除されません。"
								button = widget Wx::Button, :name => 'detail_button', :label => '削除されるファイルの一覧を表示'
								
							end
						end
						
						
						pages << widget(Wx::WizardPageSimple, :style => Wx::CLIP_CHILDREN) do
							vbox_sizer do
								expand
							
								border MAIN_SIZER_BORDER
								widget TitleText, :name => 'uninstalling_title', :label => 'アンインストール'
								widget Wx::StaticText, :style => Wx::CLIP_CHILDREN, :name => 'uninstalling_label', :label => ''
								widget Wx::Gauge, :name => 'progress_gauge', :range => 100, :style => Wx::GA_SMOOTH
								
								widget Wx::StaticText, :name => 'uninstalling_result', :label => "\n"
							end
						end
	
						
						
	
						
						(0..(pages.size - 2)).each do |i|
							Wx::WizardPageSimple.chain(pages[i], pages[i+1])
						end
	
				
						sz = wizard.page_area_sizer
						pages.each do |page|
							sz.add(page)
						end
					end
					
					@pages = pages
	
					evt_wizard_cancel(self, :on_cancel)
					evt_wizard_finished(self, :on_finish)
					evt_wizard_page_changed(self, :on_page_change)
					evt_button(find_window_by_name('detail_button'), :on_detail)
					
					
					run_wizard(@pages.first)
					
				end
	
				def on_cancel
					exit
				end
				
				def on_finish
					exit
				end
				
				def on_detail(ev)
					dialog = DetailDialog.new(self)
					dialog.show_modal
				end
	
	
				
				def on_page_change(evt)
					buttons = {}
					self.children.each do |widget|
						if widget.label =~ /Finish|終了/ then
							widget.label = '終了'
							buttons[:finish] = widget
						elsif widget.label =~ /Next|次へ|アンインストール/ then
							widget.label = 'アンインストール実行'
							buttons[:next] = widget
						elsif widget.label =~ /Back|戻る/ then
							widget.label = '< 戻る(&B)'
							buttons[:back] = widget
						elsif widget.label =~ /Cancel|中止/ then
							widget.label = '中止(&C)'
							buttons[:cancel] = widget
						end
					end
					
					if evt.page == @pages.last then
						buttons[:back].disable
						buttons[:finish].disable
						
						console = find_window_by_name('uninstalling_label')
						gauge = find_window_by_name('progress_gauge')
						
						#registry = Rumix::Registry.load
						
						#Thread.abort_on_exception = true
						Wx::Timer.after(100) do
							app = Wx.get_app
							open(File.join(Rumix.base_dir, 'rumix.log'), 'w'){|log_io|
								# タスクの数を調べる
								console.label = "ファイル数を調査中... (0 ファイル)"
								#dir_path = registry.install_path.gsub("\\", "/")
								dir_path = Rumix.base_dir
								found = 0
								app.dispatch while app.pending
								
								paths = Rumix.delete_directory_recursively([dir_path, Rumix.start_menu_dir_path], false) do |event, path|
									case event
									when :directory, :file
										found += 1
										
										if found % 32 == 0 then
											console.label = "ファイル数を調査中... (#{found} ファイル)"
										end
									end
									app.dispatch while app.pending
								end
								
								# 削除実行
								desc = "ファイルを削除中... "
								total = paths.size
								gauge = find_window_by_name('progress_gauge')
								deleted = 0
								old_label = ''
								
								failing_entries = []
								delayed_entries = []

								
								Rumix.delete_directory_recursively([dir_path, Rumix.start_menu_dir_path], true) do |type, path|
									case type
									when :directory_ready, :file_ready
										log_io.write("#{path} deleting...")
										
									when :directory, :file
										deleted += 1
	
										label = "#{desc} (#{deleted * 100 / total}%)"
										unless old_label == label then
											old_label = label
											console.label = label
										end
										gauge.value = deleted * 100 / total
										
										log_io.write("ok.\n")
										log_io.puts("deleted: #{deleted}  total: #{total}")
									when :delayed_deleting_success
										log_io.puts("delay until reboot.")
										delayed_entries << path
									when :delayed_deleting_failure
										log_io.puts("failure.")
										log_io.puts("(MoveFileEx() of Win32API might not be implemented.)")
										failing_entries << path
									end
									app.dispatch while app.pending
								end
								
									
								console.label = 'アンインストールを完了しました。'
								win = find_window_by_name('uninstalling_result')
								
								buf = ''
								unless delayed_entries.empty? then
									buf << "#{delayed_entries.size} ファイルは再起動後に削除\n"
								end
								unless failing_entries.empty? then
									buf << "#{failing_entries.size} ファイルの削除に失敗\n"
								end
								win.label = buf
								
								buttons[:finish].enable
								buttons[:cancel].disable
							}
						end # after
					end
				end
				
				
			end
	
			
			
			
		end
		
		
	end
	
	
	
	if $LOADED_FEATURES.include?('exerb/mkexy.rb') then
		puts "- test run for Exerb -"
	else
		Wx::App.run do
			wizard = Rumix::Widget::Wizard.new(nil, :title => "Rumix #{Rumix::VERSION} Uninstall")
		end
	end

rescue Exception
	if $!.kind_of?(SystemExit) then
		raise $!
	else
		open(File.join(Rumix.base_dir, 'general_error.log'), 'w'){|f|
			f.puts "#{$!.to_s} (#{$!.class.to_s})"
			f.puts $!.backtrace
		}
		raise $!
	end
	
	
end
