# encoding: utf-8

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

$LOAD_PATH.unshift 'lib'

require 'yaml'
require 'rumix/wx'


begin
	module Rumix
		module Widget
			
			
			class Wizard < Wx::Wizard
			
				def initialize(*args)
					super
					
					pages = []
					config = Rumix::Config.new.load_ini_file('rumix.ini')
					registry = Rumix::Registry.load
	
					
					construct_children do |wizard|
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								border MAIN_SIZER_BORDER
								widget TitleText, :label => 'Welcome to Rumix'
								addition = (config.ruby_type == Rumix::Config::RUBY_191 ? '（ruby 1.9.1 版）' : '')
								widget Wx::StaticText, :label => "Rumix #{Rumix::VERSION}#{addition} のインストールを開始します。\n「次へ」をクリックしてください。"

								proportion 1
								@location_args[1] |= (Wx::ALIGN_RIGHT | Wx::ALIGN_BOTTOM)
								
								path = 'res/image/ce_jacas/ruby_logo_text_bottom.png'
								if File.exist?(path) then
									widget Wx::StaticBitmap, :label => Wx::Bitmap.new(path, Wx::BITMAP_TYPE_PNG)
								end
								
								proportion 0
								widget Wx::StaticText, :label => "インストールされる ruby:\n#{config.ruby_description}"
								
							end
						end
						
						
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								border MAIN_SIZER_BORDER
								widget TitleText, :label => 'インストール先指定'
								widget Wx::StaticText, :label => "Rumixのインストール先を指定してください。\n指定した位置にフォルダが存在しない場合は、自動的に作成します。"
								
								expand
								hbox_sizer do
									border 4
									
									proportion 1
									widget Wx::TextCtrl, :value => (registry.install_path || 'C:\\rumix'), :name => 'dest'
									proportion 0
									widget Wx::Button, :label => '参照' do |button|
										wizard.evt_button(button, :on_select_dest)
									end
								end
							end
						end
			
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								expand
								border MAIN_SIZER_BORDER
								widget TitleText, :label => '外部ライブラリのインストール先指定'
								widget Wx::StaticText, :label => "rubyを使うのに必要な、各種外部ライブラリ（zlib, readline, iconv, ...）を\nインストールする場所を選択してください。"
								
								items = []
								items << OptionItem.new('ext_system', 'システムフォルダ [推奨]', "Windowsの標準システムフォルダにインストールします。\n  パス: #{Rumix.system_folder_path}", false, {:description_name => 'ext_system_description'})
								items << OptionItem.new('ext_ruby', 'rubyと同じ場所', wizard.get_ext_ruby_description('-'), false, {:description_name => 'ext_ruby_description'})
								items << OptionItem.new('ext_manual', '他の場所', "自分でパスを指定します。", false, {:path_name => 'ext_dest', :path_default => 'C:\\'})
								items << OptionItem.new('ext_no', 'インストールしない')
								widget RadioOptionPanel, items
							end
						end	
			
				
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								expand
								border MAIN_SIZER_BORDER
								widget TitleText, :label => 'Rubyリファレンスマニュアルの選択'
								widget Wx::StaticText, :label => "インストールするRubyリファレンスマニュアルの形式を選択してください。"
								
								items = []
								if config.ruby_type == Config::RUBY_191 then
									#items << OptionItem.new('man_new_chm', '新リファレンス HTML Help版 [推奨]', "「リファレンスマニュアル刷新計画」により、作成が進んでいる\n新しいリファレンスマニュアル（ruby 1.9.1 版）です。")
									items << OptionItem.new('man_chm', 'HTML Help版 [推奨]', "一つのヘルプファイル（.chm）にまとめられたリファレンスです。\n（ruby 1.9.1には対応していません）")
									items << OptionItem.new('man_html', '分割HTML版', "複数のHTMLファイルで構成されたリファレンスです。\n任意のブラウザで見たい場合には、こちらを選択してください。\n（ruby 1.9.1 には対応していません）")
								else
									items << OptionItem.new('man_chm', 'HTML Help版 [推奨]', "一つのヘルプファイル（.chm）にまとめられたリファレンスです。")
									items << OptionItem.new('man_html', '分割HTML版', "複数のHTMLファイルで構成されたリファレンスです。\n任意のブラウザで見たい場合には、こちらを選択してください。")
									#items << OptionItem.new('man_new_chm', '新リファレンス HTML Help版', "「リファレンスマニュアル刷新計画」により、作成が進んでいる\n新しいリファレンスマニュアル（ruby 1.8.7 版）です。\n情報の新しさでは一番ですが、ページや目次の一覧性に難があるため\n初心者にはお勧めできません。")
									items << OptionItem.new('man_no', 'インストールしない')
								end
								
								widget RadioOptionPanel, items
							end
						end	
						
						
						unless config.tool_list.empty? then
						
							pages << widget(Wx::WizardPageSimple) do |page|
								vbox_sizer do
									expand
									border MAIN_SIZER_BORDER
									widget TitleText, :label => '関連ツールの選択'
									widget Wx::StaticText, :label => "同時にインストールするツールを選んでください。\nよく分からない場合は、とりあえず全部入れておくのがお勧めです。"
									
									hbox_sizer do
										border 4
										expand
									
										choices = config.tool_list.map{|x| x.name}
										widget Wx::CheckListBox, :name => 'tool_list', :choices => choices, :label => 'NYACUS' do |list|
											choices.size.times do |i|
												list.check(i)
											end
											
											list.evt_listbox(list) do |evt|
												case config.tool_list[evt.index].id
												when :exerb
													desc = '　Rubyのスクリプト・拡張ライブラリを、単一で動作可能なWindows実行形式ファイルに変換するソフトウェアです。'
												when :rake
													desc = '　Ruby-Make、つまりMakeによく似たビルドツールです。Rubyスクリプトを使って柔軟なビルドを定義することができます。'
												when :rubygems
													desc = '　Ruby用のパッケージ管理システムです。新しいライブラリやツールの導入/削除、バージョンアップなどを行ってくれます。'
												when :facets
													desc = '　Rubyを便利にしてくれる、小さな拡張スクリプトの詰め合わせライブラリです。String, Array, Hash, Kernelなどの組み込みクラスに、便利なメソッドが追加されます。（注：Rumix版独自のバグ修正あり）'
												when :visualuruby
													desc = '　Windows上で動くGUIアプリケーションを楽に作るためのライブラリです。リファレンスマニュアルと、マウスで手軽にウインドウを配置できるツール「FormDesigner」も同梱しています。'
												end
												page.find_window_by_name('tool_description').value = desc
											end
										end
										
										proportion 1
										widget(Wx::TextCtrl, :style => Wx::TE_READONLY | Wx::TE_MULTILINE,
										       :name => 'tool_description', :value => 'ツールを選択すると、ここに解説が表示されます。')
									end
								end
							end	
						end
						
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								expand
								border MAIN_SIZER_BORDER
								widget TitleText, :label => 'コマンドラインシェルの選択'
								widget Wx::StaticText, :label => "同時にインストールするコマンドラインシェルの種類を選択してください。"
								
								items = []
								items << OptionItem.new('shell_nyacus', 'NYACUS 2.30 [推奨]', "tsch ライクなコマンドラインシェルです。\nWindows NT, 2000, XPをお使いの場合には、こちらを選択してください。", true)
								items << OptionItem.new('shell_nyados', 'NYADOS 2.30', "tsch ライクなコマンドラインシェル（DOS環境用）です。\nWindows 98, MEをお使いの場合には、こちらを選択してください。")
								items << OptionItem.new('shell_no', 'インストールしない')
								widget RadioOptionPanel, items
							end
						end	
						
		
	
						pages << widget(Wx::WizardPageSimple) do |page|
							vbox_sizer do
								expand
								border MAIN_SIZER_BORDER
								widget TitleText, :label => 'オプション'
								widget Wx::StaticText, :label => "よく分からない場合は、チェックを入れたまま次に進んでください。"
								
								items = []
								items << OptionItem.new('add_path_env', "環境変数PATHに ruby.exe のパスを追加する [推奨]", nil, true)
								items << OptionItem.new('add_start_menu', "スタートメニューにRumixを追加する", nil, true)
								items << OptionItem.new('no_force_overwriting', "すでにファイルが存在する場合、新しいファイルのみ上書き", nil, true)
								widget CheckOptionPanel, items
								
							end
						end	
	
			
						
						pages << widget(Wx::WizardPageSimple) do
							vbox_sizer do
								expand
							
								border MAIN_SIZER_BORDER
								widget TitleText, :label => '最終確認'
								widget Wx::StaticText, :label => "実行する内容を確認してください。"
								widget Wx::ListBox, :name => 'operation_list'
								widget Wx::StaticText, :label => "「インストール」を押すと開始します。"
							end
						end
						
						pages << widget(Wx::WizardPageSimple, :style => Wx::CLIP_CHILDREN) do
							vbox_sizer do
								expand
							
								border MAIN_SIZER_BORDER
								widget TitleText, :name => 'installing_title', :label => 'インストール'
								widget Wx::StaticText, :style => Wx::CLIP_CHILDREN, :name => 'installing_label', :label => ''
								widget Wx::Gauge, :name => 'progress_gauge', :range => 100, :style => Wx::GA_SMOOTH
							end
						end
	
						
						(0..(pages.size - 2)).each do |i|
							Wx::WizardPageSimple.chain(pages[i], pages[i+1])
						end
	
						wizard.update_operation_list
				
						sz = wizard.page_area_sizer
						pages.each do |page|
							sz.add(page)
						end
					end
					
					@pages = pages
					
					evt_wizard_finished(self, :on_finish)
					evt_wizard_page_changed(self, :on_page_change)
					evt_wizard_cancel(self, :on_cancel)
				
					run_wizard(@pages.first)
					
				end
				
				def on_select_dest
					dialog = Wx::DirDialog.new(self, :message => 'インストール先の選択：', :default_path => find_window_by_name('dest').value)
					if dialog.show_modal == Wx::ID_OK then
						find_window_by_name('dest').value = dialog.path
					end
					
				end
				
				def update_operation_list
					list = find_window_by_name('operation_list')
					list.clear
					
					
					
					make_rumix_config.operation_list.each do |op|
						list.append(op)
					end
				end
				
				def make_rumix_config
					conf = Rumix::Config.new(find_window_by_name('dest').value.gsub('\\', '/'))
					conf.load_ini_file('rumix.ini')
					
					if find_window_by_name('ext_system').value then
						conf.ext_dest_type = :system
					elsif find_window_by_name('ext_ruby').value then
						conf.ext_dest_type = :ruby
					elsif find_window_by_name('ext_manual').value then
						conf.ext_dest_type = :manual
						conf.ext_dest_dir_manual = find_window_by_name('ext_dest_text').value.gsub('\\', '/')
					end
	
	
					if find_window_by_name('man_chm').value then
						conf.man_type = :chm
					elsif find_window_by_name('man_html').value then
						conf.man_type = :html
					#elsif find_window_by_name('man_new_chm').value then
					#	conf.man_type = :new_chm
					end
					
					if find_window_by_name('shell_nyacus').value then
						conf.shell_type = :nyacus
					elsif find_window_by_name('shell_nyados').value then
						conf.shell_type = :nyados
					end
					
					tool_list_window = find_window_by_name('tool_list')
					if tool_list_window then
						conf.tool_list.each_with_index do |tool, i|
							if tool_list_window.is_checked(i) then
								conf.installing_tool_ids << tool.id
							end
						end
					end
	
	
					if find_window_by_name('add_path_env').value then
						conf.add_path_env = true
					end
					
					if find_window_by_name('add_start_menu').value then
						conf.add_start_menu = true
					end
					
					conf.force_overwriting = !(find_window_by_name('no_force_overwriting').value)
	
					
					return conf
	
				end
				
				def on_finish
					exit
				end
				
				def on_cancel
					exit
				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
							if evt.page == @pages[-2] then
								widget.label = 'インストール'
							else
								widget.label = '次へ(&N) >'
							end
							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
					
					text = find_window_by_name('ext_ruby_description')
					text.label = get_ext_ruby_description(File.join(find_window_by_name('dest').value, 'ruby/bin').gsub('/', '\\'))
					
					if evt.page == @pages[-2] then
						update_operation_list
					elsif evt.page == @pages.last then
						buttons[:back].disable
						buttons[:finish].disable
						
						console = find_window_by_name('installing_label')
						gauge = find_window_by_name('progress_gauge')
						
						Wx::Timer.after(100) do
							app = Wx.get_app
							dispatcher = nil
							open('rumix.log', 'w'){|log_io|
								config = make_rumix_config
								app.dispatch while app.pending
								
								# タスクの数を調べる
								console.label = 'ファイル数を調査中...'
								total = 0
								
								total += get_zip_file_number(config.ruby_src_zip_name)
								app.dispatch while app.pending
								
								total += get_zip_file_number('uninstaller.zip')
								app.dispatch while app.pending
								
								
								case config.man_type
								when :new_chm
									case config.ruby_type
									when Config::RUBY_18
										total += get_zip_file_number('rubyman-newchm-18.zip')
									when Config::RUBY_191
										total += get_zip_file_number('rubyman-newchm-191.zip')
									end
								when :chm
									total += get_zip_file_number('rubyman-chm.zip')
								when :html
									total += get_zip_file_number('rubyman-html.zip')
								end
								app.dispatch while app.pending
									
								case config.shell_type
								when :nyacus
									total += get_zip_file_number('nyacus.zip')
									total += get_zip_file_number('_nya.zip')
								when :nyados
									total += get_zip_file_number('nyados.zip')
									total += get_zip_file_number('_nya.zip')
								end
								app.dispatch while app.pending
								
								if config.ext_dest_dir then
									total += get_zip_file_number('ext.zip')
								end
								app.dispatch while app.pending
									
								config.installing_tool_ids.each do |tool_id|
									total += config.tool_list.find{|x| x.id == tool_id}.weight
								end
								app.dispatch while app.pending
								total += 1 if config.add_path_env?
								total += 1 if config.add_start_menu?
								
								
								i = 0
								
								desc = ''
								old_label = ''
								Rumix::Application.run(config, log_io){|event_id, args|
									app.dispatch while app.pending

									case event_id
									when :on_uninstaller_install_start
										desc = 'アンインストーラをインストール中...'
									when :on_ruby_install_start
										desc = 'rubyをインストール中...'
									when :on_ext_install_start
										desc = '外部ライブラリをインストール中...'
									when :on_man_install_start
										desc = 'リファレンスマニュアルをインストール中...'
									when :on_man_install_complete
										if config.man_type == :chm then
											i += 1
										end
									when :on_tool_install_start
										tool_name = config.tool_list.find{|x| x.id == args[0]}.name
										desc = "#{tool_name}をインストール中..."
										
										# GUIインストーラ上では、Threadを使用して
										# ウインドウが固まってしまわないようにする
										Thread.abort_on_exception = true
										dispatcher = Thread.new{
											loop do
												gauge.pulse
												app.dispatch while app.pending
												sleep(0.05)
											end
										}

									when :on_tool_install_complete
										i += config.tool_list.find{|x| x.id == args[0]}.weight
										Thread.kill(dispatcher)
										
									when :on_path_env_add_start
										desc = "PATH環境変数を設定中..."
									when :on_start_menu_add_start
										desc = "スタートメニューへショートカットを追加中..."
									when :on_path_env_add_complete, :on_start_menu_add_complete
										i += 1
									when :on_child_installed
										i += 1
									when :on_complete
										i = total
										desc = "インストール完了"
									end
									
									label = "#{desc} (#{i * 100 / total}%)"
									unless old_label == label then
										old_label = label
										console.label = label
									end
									gauge.value = i * 100 / total
									
								}
								console.label = 'complete.'
								buttons[:finish].enable
								buttons[:cancel].disable
							}
						end
							
					end
				end
				
				def get_ext_ruby_description(path)
					"Rumixに含まれるrubyと同じ場所にインストールします。\n  パス: #{path}"
				end
				
				def get_zip_file_number(name)
					re = nil
					Zip::Archive.open(File.join('package', name)){|zip|
						list = []
						zip.each do |file|
							list << file.name
						end
				
						if list.include?('content/') then
							re = list.find_all{|x| x =~ /^content\//}.size
						else
							re = list.size
						end
					}
					
					re
				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}")
		end
	end

rescue Exception
	open('general_error.log', 'w'){|f|
		f.puts $!.to_s
		f.puts $!.backtrace
	}
	
	raise $!
	
end