
module DarkHall
	# SDLデバイスの初期化やデータファイルの読み込みなどを行う特殊フェーズ
	# ゲーム起動時には、必ずこのフェーズを通す必要がある
	class InitializingPhase < Phase
		def initialize(test_run = false)
			@test_run = test_run
		end
	
		def on_enter(from)
			super
			
			# グローバル変数と基本的なデバイス、およびタイマーの初期化を行う
			Game.init_global_variables
			
			sdl_step
			screen_step
			timer_step
			
			# MEMO: タイトルの流れをスイッチする用の変数。完成版では消すべき
			$new_title = false
			$logo_position ||= :right_bottom
			unless $logo then
				#src = Util.random_pick(%w(logo_b_1.png logo_c_1.png logo_d_3.png roman4.png))
				#src = 'roman3.png'
				src = 'DH_logo.png'
				$logo = Res.load_picture(src)
				
				case $logo_position
				when :center
					$logo_x, $logo_y = (SCREEN_WIDTH - $logo.w) / 2, (SCREEN_HEIGHT - $logo.h) / 2
				when :right_bottom
					$logo_x, $logo_y = (SCREEN_WIDTH - $logo.w - 16), (SCREEN_HEIGHT - $logo.h - 16)
				when :up
					$logo_x, $logo_y = (SCREEN_WIDTH - $logo.w) / 2, 64
				else
					raise
				end
			end
			
			@logo_window = PictureWindow.new.make_surface($logo).set_position($logo_x, $logo_y)
			@state_window = DoubleTextWindow.new
			@state_window.has_frame = false
			@state_window.make_surface(400, 10).update.set_position(16, 16)
			$windows = [@logo_window, @state_window]
		
			state_texts = @state_window.texts.clear
			state_texts << [_("画面の初期化を完了しました")]
			state_texts << [_("音楽デバイスを初期化しています...")]
			@state_window.update
			Game.force_refresh

			sound_step
			
			state_texts.last[0] += _("完了.")			
			state_texts << [_("ゲームコントローラを初期化しています...")]
			@state_window.update
			Game.force_refresh
			
			joystick_step
			
			state_texts.last[0] += _("完了.")
			state_texts << [_("サーフィスを初期化しています...")]
			@state_window.update
			Game.force_refresh
			
			surface_step
			
			state_texts.last[0] += _("完了.")
			state_texts << [_("データベースファイルを読み込んでいます...")]
			@state_window.update
			Game.force_refresh
			
			db_step
			
			state_texts.last[0] += _("完了.")			
			@state_window.update
			Game.force_refresh
			Game.wait(5)
			
			
			
			if @test_run then
				Game.quit
			else
				Phase.change(LogoPhase.new(@logo_window))
			end
		end
		
		private
		
		def sdl_step
			SDL.init(SDL::INIT_EVERYTHING)
		end
		
		def screen_step
			Game.full_screen = ($option_info and $option_info.full_screen) || SETTING.full_screen?
			Game.open_screen(Game.full_screen?)
			LOGGER.log(VideoInitializedLog)
			
			SDL::WM.set_caption(WINDOW_CAPTION, WINDOW_CAPTION)
		end
		
		def timer_step
			Game.timer = FPSTimerLight.new(FPS)
			Game.timer.reset
			LOGGER.info("タイマーを#{FPS}FPSで初期化")
		end
		
		def sound_step
			SDL::Mixer.open(SETTING.mixer_frequency, SDL::Mixer::DEFAULT_FORMAT, 2, SETTING.mixer_chunk_size)

			frequency, format, channels = SDL::Mixer.spec
			format_str = case format
			when SDL::Mixer::FORMAT_U8 then "U8"
			when SDL::Mixer::FORMAT_S8 then "S8"
			when SDL::Mixer::FORMAT_U16LSB then "U16LSB"
			when SDL::Mixer::FORMAT_S16LSB then "S16LSB"
			when SDL::Mixer::FORMAT_U16MSB then "U16MSB"
			when SDL::Mixer::FORMAT_S16MSB then "S16MSB"
			else "Unknown"
			end
			
			LOGGER.puts "SDL-Mixer Opened."
			
			LOGGER.puts "  Frequency: #{frequency}"
			LOGGER.puts "  Format: #{format_str}"
			LOGGER.puts "  Channel: #{channels}"
			LOGGER.puts "  Chunk-Size: #{SETTING.mixer_chunk_size}"

		
			Game.timelog('Sound Loading'){
				SE.load
				BGM.load
				LOGGER.info("音楽デバイス初期化成功")
			}
		end
		
		def joystick_step
			# キー初期化
			$joysticks = []
		
			(0...(SDL::Joystick.num)).each do |i|
				$joysticks[i] = SDL::Joystick.open(i)
			end
			LOGGER.log(JoystickInitializedLog)
	
		
			SDL::Key.enable_key_repeat(240, 120)
		end
		
		def surface_step
			# 敵グラフィックやHPゲージのサーフェス初期化
			$dark_surface = $screen.display_format_alpha
			$dark_surface.fill_rect(0, 0, 640, 480, [0, 0, 0, 150])
			$enemy_graphic_control.load
			
			Game.gauge_surfaces = {}
			
			list = [:hp, :hp_small, :exp]
			list.each do |type|
				table = Game.gauge_surfaces[type] = {}
				table[:base] = Res.load_picture("#{type}.png")
				table[:base] = table[:base].display_format
				
			
				table[:back] = SDL::Surface.new(0, table[:base].w, table[:base].h, $screen)
				table[:back].fill_rect(0, 0, table[:base].w, table[:base].h, [60, 60, 60])
				table[:back] = table[:back].display_format
				
				table[:decrease] = SDL::Surface.new(0, table[:base].w, table[:base].h, $screen)
				table[:decrease].fill_rect(0, 0, table[:base].w, table[:base].h, [100, 40, 40])
				table[:decrease] = table[:decrease].display_format
				
				case type
				when :hp
					table[:warning] = Res.load_picture("#{type}_warning.png")
					table[:warning] = table[:warning].display_format
				else
					table[:warning] = table[:base]
				end
			
			end
			
			PARTY_WINDOW.make_surface.update
			MESSAGE_WINDOW.make_surface(SCREEN_WIDTH - 16*2, 6)
			DESCRIPTION_WINDOW.make_surface
			SEAL_WINDOW.make_surface
			ITEM_DATA_WINDOW.make_surface
		end
		
		def db_step
			Game.init_data
		end
	end
	
	class LogoPhase < Phase
		def initialize(logo_window)
			@logo_window = logo_window
		end
	
		def on_enter(from)
			super
			@copyright_window = TextWindow.new
			@copyright_window.has_frame = false
			@copyright_window.align = AL_CENTER
			@copyright_window.text = "(C) 2010 Team D.H."
			@copyright_window.set_good_width.make_surface(nil).update.set_position(:center, 360)
			
			@guide_window = TextWindow.new
			@guide_window.align = AL_CENTER
			@guide_window.text = "Press any key"
			@guide_window.set_good_width.make_surface(nil).update
			@guide_window.dock_beside(@copyright_window, :bottom, 32).set_position(:center, nil)

			
			if $new_title then
				$windows = [@guide_window, @copyright_window, @logo_window]
			else
				$windows = [@logo_window]
				on_enter_key
			end
			
		end
		
		def on_enter_key
			@guide_window.hide
			Phase.change(TitlePhase.new($windows.dup))
		end
	end

	class TitlePhase < Phase
		include GetText
		Bar = Struct.new(:id, :name, :select_caption, :keycode)
		
		BARS = []
		BARS << Bar.new('n', _('北の酒場'), _('北の酒場(N)'), SDL::Key::N)
		BARS << Bar.new('e', _('東の酒場'), _('東の酒場(E)'), SDL::Key::E)
		BARS << Bar.new('s', _('南の酒場'), _('南の酒場(S)'), SDL::Key::S)
		BARS << Bar.new('w', _('西の酒場'), _('西の酒場(W)'), SDL::Key::W)
			
		def initialize(under_windows = nil)
			@under_windows = under_windows || [PictureWindow.new.make_surface($logo).set_position($logo_x, $logo_y)]
		end
		
	
		def on_enter(from)
			super
			
=begin
			@title = TextWindow.new
			def @title.ttf
				@ttf ||= SDL::TTF.open('res/font/ume-tgc5.ttf', 30)
				@ttf.style = SDL::TTF::STYLE_BOLD
				
				@ttf
			end
			@title.has_frame = false
			@title.height = 100
			@title.align = AL_CENTER
			@title.make_surface('DarkHall').update.show
			
			
			@press = TextWindow.new
			@press.has_frame = false
			@press.align = AL_CENTER
			@press.make_surface('Press any key').update.show
			
			@c = TextWindow.new
			@c.has_frame = false
			@c.align = AL_CENTER
			@c.make_surface('(c) Team D.H. 2009').update.show
			
			@title.set_position(:center, 130)
			@press.set_position(:center, 300)
			@c.dock_beside(@press, :bottom).set_position(:center, nil)
			return
=end
			#BGM.stop
			

			
			@description = TextWindow.new
			@description.text = _('使用するセーブデータを選択してください')
			@description.set_good_width.make_surface.update.show
			@description.set_position(nil, 150)
			
			#@title_name_window = TitleNameWindow.new
			#@title_name_window.make_surface
			#$logo.set_alpha(SDL::SRCALPHA, 160)
			#@title_name_window = PictureWindow.new.make_surface($logo).set_position($logo_x, $logo_y)
			
			@under_windows.each do |win|
				#win.front_surface.set_alpha(SDL::SRCALPHA, 160)
			end
			
			
			@main_window = MultiColumnWindow.new
			columns = @main_window.columns.clear
			columns << ColumnItem.new('', [], 80, AL_LEFT)
			columns << ColumnItem.new(s_('ColumnCaption|WEEK'), [], 60, AL_RIGHT, 8)
			columns << ColumnItem.new(s_('ColumnCaption|LAST SAVED'), [], 140, AL_CENTER)
			columns << ColumnItem.new('', [], 30, AL_CENTER, 0)
			
			@dir_path = SETTING.save_path
			
			
			update_saves
			index = @main_window.index
			@main_window.set_good_width.make_surface(nil, @main_window.select_items.size)
			@main_window.dock_beside(@description, :bottom)
			@main_window.set_position(:center, nil)
			@main_window.index = index
			
			


			@help = DoubleTextWindow.new
			@help.texts = [[_('数字キーの[1]'), _('操作方法を確認する')], ['[D]', _('選択データの削除')]]
			@help.set_good_width.make_surface(nil, 2).update.show
			@help.dock_beside(@main_window, :bottom_right)


			@description.left = @main_window.left
			
			#$windows = [@title_name_window, @description, @help, @main_window]
			$windows = @under_windows + [@description, @help, @main_window]
			
			@main_window.warp
			

		end
		
		def update_saves
			saves = []
			items = @main_window.select_items.clear
			columns = @main_window.columns
			columns.each{|x| x.captions.clear}
			@beta_cleared = false
			
			BARS.each do |bar|
				items << SelectItem.new(bar.id, bar.select_caption, bar.keycode)
				save = SaveData.new(@dir_path, bar.id)
				
				if save.exist? then
					models = save.load_mpac_models
					switch = Switch.create_from_mpac_model(models['switch'])
					columns[1].captions << models['week']
					columns[2].captions << save.mtime.strftime("%Y-%m-%d %H:%M")
					
					if models['rule'] then
						case models['rule']['_object_class']
						when 'DarkHall::ShortTimeRule'
							rule_letter = 'S'
						when 'DarkHall::HardRule'
							rule_letter = 'H'
						when 'DarkHall::SorcererAttackRule'
							rule_letter = '*'
						else
							rule_letter = ''
						end
					else
						rule_letter = ''
					end
					
					columns[3].captions << ((switch['BetaScenarioClear'] ? 'C' : '') + rule_letter)
					
					if switch['BetaScenarioClear'] and switch['RuleSelectable'] then
						@new_beta_cleared = true
					end
					
					saves << save
				else
					columns[1].captions << ''
					columns[2].captions << ''
					columns[3].captions << ''
				end
			end

			unless saves.empty? then
				latest = saves.sort_by{|x| x.mtime}.last
				@main_window.set(latest.id)
			end

		end
		
		def on_select(id)
			$savedata = SaveData.new(@dir_path, id)
			if $savedata.exist? then
				msg = _("%{bar}で冒険を始めます。\nよろしいですか？")
			else
				msg = _("新しいセーブデータを作成します。\nよろしいですか？")
			end
			
			if Game.ask(msg.evaluate(:bar => BARS.find{|x| x.id == id}.name)) then
				if $savedata.exist? then
					Game.working(_('ロード中...')){
						$savedata.load
					}
				else
					$windows.clear
					
					selected_rule = nil
					if Game.debug_mode or Input.ctrl_pressed? or @new_beta_cleared then
						if Game.ask(_("ゲームのルールを変更しますか？\n\nルールを変更すると、敵の強さや経験値の量などが変化します\n（ゲーム中にルールを変更し直すことはできません）")) then
							old_phase = $phase
							Phase.change(RuleSelectPhase.new)
							selected_rule = Game.operation_loop
							
							unless selected_rule then
								Phase.change(old_phase)
								return
							end
						end
					end
				
					msg = _("自動で作成される6人のキャラクターを使いますか？\n（使わない場合、自分でキャラクターを作成する必要があります）")
					if !(selected_rule) or !(selected_rule.use_member_classes) then
						re = Game.ask(msg, :silent => true)
					end
					
					SE.select
					GS.ready
					GS.rule = selected_rule if selected_rule
					
					if re then
						classes = [Fighter, HeavyFighter, HeavyFighter, Archer, Magician, Explorer]
						classes.each do |cls|
							age = Util.random_pick([AGE::YOUNG, AGE::YOUNG, AGE::YOUNG, AGE::ELDER, AGE::CHILD])
							Game.add_default_member(cls, 1, age)
						end
					end
					GS.check_oneself
					Game.reporter = Reporter.new("./report/#{id}/")
					Game.reporter.check_dir
					Game.save
					Game.message(_("セーブデータを作成しました。冒険を始めます"))
				end
				Game.reload_ttf
				
				# セーブ時のパーティーが迷宮にいる場合、新しいパーティーを作って街から再開
				if GS.party.in_dungeon? then
					GS.change_to_new_party
				end
				
				Phase.change(TownMenuPhase.new)
			else
				@main_window.warp
			end
		end
		
		def on_cancel
			super
			Phase.change(LogoPhase.new(@under_windows.last))
		end
		
		def on_key_press(keycode)
			if Game.current_window == @main_window then
				case keycode
				when SDL::Key::M
					raise('Sample Exception.')
				when SDL::Key::D
					bar = BARS.find{|x| x.id == @main_window.current_id}
					save = SaveData.new(@dir_path, bar.id)
					if save.exist? then
						SE.select
						
						if Game.ask(_("セーブデータを削除します。\n$c[bad]（一度削除したセーブデータは元に戻せません）$c\n\n本当によろしいですか？"), :default => :no) then
							save.file_path.delete
							update_saves
							@main_window.update
						end
					else
						SE.cancel
					end
				when SDL::Key::K1
					SE.select
					
=begin
					
					win = MultiColumnWindow.new
					win.columns << ColumnItem.new('', [_('決定'), _('キャンセル')], 90)
					win.columns << ColumnItem.new('KEYBOARD', ['[Z][Enter][Space]', '[X][Esc][Backspace]'], 150)
					win.columns << ColumnItem.new('MOUSE', [_('左クリック'), _('右クリック')], 90)
					win.columns << ColumnItem.new('GAME PAD', [_('ボタン1'), _('ボタン2')], 60)
	
					win.set_good_width
					win.make_surface(nil, 2).update
					win.centering_on_screen
=end

				
					old = $windows
					$windows = []
					
					#@title_name_window.show
					
					title = TextWindow.new
					title.align = AL_CENTER
					title.has_frame = false
					title.text = _('- 基本操作 -')
					title.make_surface(SCREEN_WIDTH - 8*2).update
					title.set_position(:center, 16).show
					
					win1 = TextWindow.new.make_surface(_('キーボード'), 1, AL_CENTER)
					win1.update.dock_beside(title, :bottom, 16).show
					win1.left += 32
					win2 = DoubleTextWindow.new
					win2.has_frame = false
					texts = []
					texts << [_('決定:'), _('[Z][Enter][Space]')]
					texts << [_('キャンセル:'), _('[X][Esc][Backspace]')]
					win2.texts = texts
					win2.set_good_width.make_surface(240, 2).update
					win2.dock_beside(win1, :bottom).show
					
					win3 = TextWindow.new.make_surface(_('マウス'), 1, AL_CENTER)
					win3.update.dock_beside(win2, :bottom, 32).show
					win4 = DoubleTextWindow.new
					win4.has_frame = false
					texts = []
					texts << [_('決定:'), _('左クリック')]
					texts << [_('キャンセル:'), _('右クリック')]
					win4.texts = texts
					win4.set_good_width.make_surface(240, 2).update
					win4.dock_beside(win3, :bottom).show
					
					win5 = TextWindow.new.make_surface(_('ゲームパッド'), 1, AL_CENTER)
					win5.update.dock_beside(win4, :bottom, 32).show
					win6 = DoubleTextWindow.new
					win6.has_frame = false
					texts = []
					texts << [_('決定:'), _('ボタン1')]
					texts << [_('キャンセル:'), _('ボタン2')]
					win6.texts = texts
					win6.set_good_width.make_surface(240, 2).update
					win6.dock_beside(win5, :bottom).show
					
					win2.left += 16
					win4.left += 16
					win6.left += 16
					
					win7 = TextWindow.new.make_surface(400, 4)
					win7.has_frame = false
					win7.word_wrap_length = 20
					win7.update(_("・ゲームパッドのボタン配置は\n　あとから変更可能"))
					win7.dock_beside(win1, :right)
					win7.left = win2.right + 64
					win7.show


					
					help = TemporaryTextWindow.new
					help.make_surface(_('決定キーで閉じる'), 1, AL_CENTER).update
					help.dock_beside(win6, :bottom, 32).set_position(:center, nil).show
	
					
					
					Game.operation_loop
					$windows = old
					
				end
			end
		end
		
	end
	
	class RuleSelectPhase < Phase
		def on_enter(from)
			@main_window = SelectableWindow.new
			items = @main_window.select_items
			items << SelectItem.new(:NormalRule, 'ノーマル（標準）')
			items << SelectItem.new(:ShortTimeRule, 'ショートタイム (進行が早い)')
			items << SelectItem.new(:HardRule, 'ハード (難しい)')
			#items << SelectItem.new(:SurvivalRule, 'サバイバル')
			#items << SelectItem.new(:DeepRule, 'ディープ')
			items << SelectItem.new(:SorcererAttackRule, 'ソーサラーアタック')
			#items << SelectItem.new(:custom, '自分でルールを設定する')
			items << SelectItem.new(:cancel, '前の画面に戻る')
			
			@main_window.set_good_width.make_surface(nil, items.size).update
			
			@feature_window = DoubleTextWindow.new
			@feature_window.make_surface(300, 10)
			
			@feature_window.centering_on_screen
			@main_window.top = @feature_window.top
			Window.centering_x([@main_window, @feature_window])
			
			DESCRIPTION_WINDOW.update(_('ルールを選択してください')).set_position(8, 8)
			@main_window.warp
			
			on_change
			
			$windows = [DESCRIPTION_WINDOW, @feature_window, @main_window]
		end
		
		def on_change
			texts = []
			case @main_window.current_id
			when :NormalRule
			when :ShortTimeRule
				texts << ['敵から得られる経験値1.5倍', nil]
				texts << ['敵から得られる金品2倍', nil]
				texts << ['商店でマップ表示アイテムを購入可能', nil]
			when :HardRule
				texts << ['蘇生・再生料金3倍', nil]
				texts << ['通常敵の能力値+8', nil]
				texts << ['ボスの能力値+12', nil]
				texts << ['ボスの行動パターンが変化', nil]
				texts << ['敵から得られる金品1/2', nil]
				texts << ['宝箱の罠が強化', nil]
			when :SorcererAttackRule
				texts << ['「術師」「学者」「僧」のみ使用可能', nil]
			else

			end
			@feature_window.update(texts)
		end
		
		def on_select(id)
			case id
			when :cancel
				on_cancel
			else
				rule = DarkHall.const_get(id).new
				throw(:exit_operation_loop, rule)
			end
		end
		
		def on_cancel
			throw(:exit_operation_loop, nil)
		end
		
	end
	
	
	
	

	
	
	
	
	

	
end
