module DarkHall
	class Phase
		def Phase.change(to, back_log = true)
			from = $phase

			# 戻り先をセット
			$back_phase = from if back_log
			# OnLeave発生
			$phase.on_leave(to) if $phase
			# 現在フェーズをセット
			$phase = to
			# OnEnter発生
			$phase.on_enter(from)
		end
		
		def Phase.back
			Phase.change($back_phase, false)
		end
		
		def message(msgs)
			Game.message(msgs)
		end
		
		def show_command_description
			if GS.game_config.command_description_visible? then
				DESCRIPTION_WINDOW.show
				$windows[-2].show
			end
		end
		
		
		
		def on_leave(to)
			# no action
		end
		
		def on_enter(from)
			PARTY_WINDOW.update
		end
		
		def on_enter_key
		end
		
		def on_shift_down
		end
		
		def on_shift_up
		end
		
		def on_ctrl_down
		end
		
		def on_ctrl_up
		end

		# 選択肢が選ばれたときに発生
		def on_select(id)
		end
		
		# 選択肢が選択された
		def on_cancel
		end
		
		# 選択肢が選ばれたときに発生
		def on_change
			win = Game.current_window
			if win.kind_of?(SelectableWindow) and win.current_item and win.current_item.description then 
				DESCRIPTION_WINDOW.update(win.current_item.description)
			end
		end
		
		def on_left_walk_key
		end
		
		def on_right_walk_key
		end
		
		
		def on_key_press(keycode)
		end

	end
	
	
	module BackablePhase
		def on_cancel
			
			Phase.back
		end

	end
	
	module MemberChangablePhase
		def on_left_key
			SE.cursor_move
			$member_index = prev_index($member_index, GS.party.members.size)
			Game.current_window.update
			PARTY_WINDOW.update_surface
			self.on_change_member
		end

		def on_right_key
			SE.cursor_move
			$member_index = next_index($member_index, GS.party.members.size)
			Game.current_window.update
			PARTY_WINDOW.update_surface
			self.on_change_member
		end
		
		def on_key_press(keycode)
			index = keycode - SDL::Key::K1
			if (0...(GS.party.member_ids.size)).include?(index) then
				$member_index = index
				SE.cursor_move
				Game.current_window.update
				PARTY_WINDOW.update_surface
				self.on_change_member
			end
		end
		
		def on_change_member
			self.on_change
		end

	end
	
	class PartySelectPhase < Phase
		def on_enter(from)
			super
			
			$windows = showing_windows
			

			items = SELECT_WINDOW.select_items.clear
			key = 1
			GS.parties.each_with_index do |party, id|
				if party.in_dungeon? then
					msg = _("%{floor}にいる%{party}") + "(#{key})"
					items << SelectItem.new(id, msg.evaluate(:floor => party.floor.name, :party => party.name), key.to_s)
					unless party.alive? then
						items.last.disable(_("全滅しています"))
					end
					key += 1
				end
			end
			if showing_cancel? then
				items << SelectItem.new(:cancel, _('キャンセル'))
			end

			SELECT_WINDOW.make_surface(240, 6).update.centering.reset_index.warp
			SELECT_WINDOW.display_max = 6
			INFORMATION_WINDOW.make_surface(360).update(self.information_text)
			INFORMATION_WINDOW.dock_beside(SELECT_WINDOW, :top)
			INFORMATION_WINDOW.set_position(:center, nil)
			WARNING_WINDOW.make_surface(200).dock_beside(PARTY_WINDOW, :top)
			WARNING_WINDOW.right = PARTY_WINDOW.right
			
			on_change
		end

		
		def on_change
			id = SELECT_WINDOW.current_id
			if id.kind_of?(Numeric) then
				GS.current_party_id = id
			else
				GS.change_to_new_party
			end
			PARTY_WINDOW.update
		end
	end
	
	
	
	# ステータス表示
	class StatusPhase < Phase
		include MemberChangablePhase
		
		attr_reader :item_window, :help_window, :name_window
		
		
		def on_enter(from)
			super
			@page = 0
			@name_window = TextWindow.new.make_surface(200).set_position(16, 16)
			@help_window = TextWindow.new
			@help_window.has_frame = false
			@help_window.make_surface(400).dock_beside(@name_window, :right)
			@profile_window = DoubleTextWindow.new.make_surface(200, 6).dock_beside(@name_window, :bottom)
			@data_window = DoubleTextWindow.new.make_surface(200, 5).dock_beside(@profile_window, :bottom)
			
			@ability_caption_window = CaptionWindow.new.make_surface(150)\
				.update(_("能力値")).dock_beside(@profile_window, :right)
			@ability_window = DoubleTextWindow.new.make_surface(150, 5).dock_beside(@ability_caption_window, :bottom, -1)
			base_top = @ability_caption_window.top
			
			
			@skill_caption_window = CaptionWindow.new.make_surface(150)\
				.update(_("特殊技能")).dock_beside(@ability_window, :bottom)
			@skill_window = DoubleTextWindow.new.make_surface(150, 2).dock_beside(@skill_caption_window, :bottom, -1)
			
			@spec_window = CharacterSpecWindow.new.make_surface(180).dock_beside(@profile_window, :right)


			@item_window = ItemWindow.new.make_surface
			@item_caption_window = CaptionWindow.new.make_surface(@item_window.width).update(_("所持品")).dock_beside(@ability_window, :right)
			@item_caption_window.top = base_top
			@item_window.dock_beside(@item_caption_window, :bottom, -1)

			@spell_caption_window = CaptionWindow.new.make_surface(200).update(_("呪文")).dock_beside(@spec_window, :right)
			@spell_caption_window.top = base_top
			@spell_window = TextWindow.new.make_surface(200, 4).dock_beside(@spell_caption_window, :bottom, -1)
			
			@detail_window = DoubleTextWindow.new
			@detail_window.dock_beside(@profile_window, :right)
			@detail_window.make_surface(200, 10)
			@detail_window.has_caption = true

			@party_detail_window = DoubleTextWindow.new
			@party_detail_window.dock_beside(@detail_window, :right)
			@party_detail_window.make_surface(200, 6)
			@party_detail_window.has_caption = true
			#$selectable_windows = [@item_window, PARTY_WINDOW]

			update_sequence
			@help_window.show
		end
		
		def on_leave(to)
			$selectable_windows.clear
		end
		
		def update_sequence
		
			PARTY_WINDOW.update
			member = Game.current_member
			@name_window.update(member.name)
			@help_window.update(_("←→：メンバー選択　　↑↓：表示変更"))

			
			
			texts = []
			texts << [_('年齢'), member.age]
			texts << [_('クラス'), member.class_caption]
			texts << [_('レベル'), member.level]
			texts << [_('経験値'), member.exp]
			if (rest = member.rest_exp_to_next) then
				texts << ["", (rest < 0 ? _("(レベルアップ可能)") : _("(次レベルまで:%{rest})").evaluate(:rest => rest))]
			else
				texts << []
			end
			texts << [_('所持金'), _("%{g}G").evaluate(:g => member.gold)]
			@profile_window.update(texts)
			
			
			texts.clear
			if member.dead? then
				texts << [_('HP'), sprintf("%s / %3d", _('DEAD'), member.hp_max)]
			else
				texts << [_('HP'), sprintf("%3d / %3d", member.hp, member.hp_max)]
			end
			texts << ["", (member.hp_max_penalty > 0 ? _("(Max減少:-%{penalty})").evaluate(:penalty => member.hp_max_penalty) : "")]
			texts << [_("状態"), member.condition_caption]
			@data_window.update(texts)

			@spec_window.update(member)


			texts.clear
			
			ABILITY_TYPES.each do |type|
				abl = member.get_ability(type)
				base = member.get_ability_base(type)
				if abl > base then
					v = "$[GoodColor]#{abl}"
				elsif abl < base then
					v = "$[BadColor]#{abl}"
				else
					v = abl.to_s
				end
				texts << [ABILITY_CAPTIONS[type], v]
			end
			@ability_window.update(texts)
			
			texts.clear
			texts << [_('鍵開け'), _("Lv") + member.skill_levels[SKILL::UNLOCK].to_s]
			texts << [_('罠外し'), _("Lv") + member.skill_levels[SKILL::REMOVE_TRAP].to_s]
			@skill_window.update(texts)
			
			@item_window.update
			
			if member.spell_caster? then
				texts.clear
				(0..3).each do |i|
					s1 = member.spells[i*2]
					s2 = member.spells[i*2+1]
					t1 = (s1 ? (DB.find_spell(s1).short_name + "(#{member.mp[s1]})") : "")
					t2 = (s2 ? (DB.find_spell(s2).short_name + "(#{member.mp[s2]})") : "")
					texts << sprintf("%-12s%-12s", t1, t2)
				end
				@spell_window.update(texts.join("\n"))
			else
				@spell_window.update("")
			end
			
			if @page == 2 then # デバッグ用
				texts = []
				texts << ['詳細データ']
				texts << ['ダメージ軽減', Calc.def2red(member.defense)]
				if member.shield then
					shield_red = Calc.def2red(member.defense + member.shield.extra_defense) - Calc.def2red(member.defense)
					texts << ['  盾', Util.bonus_to_s(shield_red)]
				else
					texts << []
				end
				texts << ['基本行動速度', member.speed]
				texts << ['術バランス補正', Util.bonus_to_s((member.magic_balance_bonus * 100).round) + '%']
				texts << ['クリーンヒット補正', Util.bonus_to_s(member.clean_hitting_bonus)]
				texts << ['生存補正', Util.bonus_to_s(member.surviving_bonus)]
				texts << ['初手逃走補正', Util.bonus_to_s(member.fast_escaping_bonus)]
				texts << ['敵逃走補正', Util.bonus_to_s(member.enemy_ousting_bonus)]
				texts << ['蘇生料金', member.revive_cost]
				@detail_window.update(texts)
				
				texts = []
				texts << ['パーティー全体']
				texts << ['敏捷さ', GS.party.agl]
				texts << ['初手逃走補正', Util.bonus_to_s(GS.party.alive_members.map{|x| x.fast_escaping_bonus}.total)]
				texts << ['敵逃走補正', Util.bonus_to_s(GS.party.alive_members.map{|x| x.enemy_ousting_bonus}.total)]
				@party_detail_window.update(texts)
			end
			

			# 表示
			$windows.clear
			$windows << PARTY_WINDOW << @help_window
			$windows << @name_window << @profile_window << @data_window
			case @page
			when 0
				$windows << @ability_window << @ability_caption_window
				$windows << @skill_window << @skill_caption_window
				$windows << @item_window << @item_caption_window
			when 1
				$windows << @spec_window
				$windows << @spell_window << @spell_caption_window
			when 2 # デバッグ用
				$windows << @detail_window << @party_detail_window
			end
			
		end
		
		def on_change_member
			super
			update_sequence
			@help_window.show
		end
		
		
		def on_enter_key
			items = []
			items << SelectItem.new(:item, _('アイテム(I)'), SDL::Key::I)
			items << SelectItem.new(:equip, _('装備の変更(E)'), SDL::Key::E)
			items << SelectItem.new(:spell, _('呪文書を開く(S)'), SDL::Key::S) if Game.current_member.spell_caster?
			items << SelectItem.new(:gather_gold, _('お金を集める(G)'), SDL::Key::G)
			items << SelectItem.new(:ai, '＊AI設定') if Game.debug_mode?
			#items << SelectItem.new(:detail, "＊詳細データ") if Game.debug_mode?
			items << SelectItem.new(:cancel, _('キャンセル'))
			@help_window.update("")
			id = Game.select(items){|window|
				window.right = @item_window.right
				window.bottom = @item_window.bottom
			}
			case id
			when :item
				@page = 0
				update_sequence
				@help_window.update("")
				@item_window.update(true)
				@item_window.show.reset_index.warp
				Phase.change(StatusItemSelectPhase.new)
			when :equip
				Phase.change(EquipPhase.new)
			when :spell
				Phase.change(StatusSpellSelectPhase.new)
			when :gather_gold
				GS.party.gather_gold
				update_sequence
				@help_window.show
			#when :mastery
			when :ai
				re = Game.select([SelectItem.new(:on, 'AIにまかせる'), SelectItem.new(:off, '自分で行動を選択する')])
				case re
				when :on
					Game.current_member.ai_act = true
				when :off
					Game.current_member.ai_act = false
				end
				PARTY_WINDOW.update
			when :cancel
				update_sequence
				@help_window.show
			end
		end
		

		
		
		def on_cancel
			case $section
			when Section::TOWN
				Phase.change(BarMenuPhase.new)

			when Section::DUNGEON
				Phase.change(CampPhase.new)

			end
			SELECT_WINDOW.set(:status).warp

		end
		
		
		def on_left_key
			super if Game.current_window == @help_window
		end
		
		def on_right_key
			super if Game.current_window == @help_window
		end
		
		def on_up_key
			SE.cursor_move
			@page = Util.prev_index(@page, (Game.debug_mode? ? 3 : 2))
			update_sequence
			@help_window.show
		end
		
		def on_down_key
			SE.cursor_move
			@page = Util.next_index(@page, (Game.debug_mode? ? 3 : 2))
			update_sequence
			@help_window.show
		end
		
		def on_key_press(keycode)
			case keycode
			when (SDL::Key::K1)..(SDL::Key::K6)
				if GS.party.members[keycode - SDL::Key::K1] then
					SE.cursor_move
					$member_index = keycode - SDL::Key::K1
				end
				
			end
			update_sequence
			@help_window.show
		end
		

	end
	
	module ItemSelectPhase
		def update_item_information(item)
			ITEM_DATA_WINDOW.update(item)
			if item then
				DESCRIPTION_WINDOW.update((item.unidentified? ? "(未識別)" : item.description))
			else
				DESCRIPTION_WINDOW.update("")
			end
		end
	end
	
	
	class StatusItemSelectPhase < Phase
		include ItemSelectPhase
		def on_enter(from)
			@status_phase = from
			DESCRIPTION_WINDOW.show
			DESCRIPTION_WINDOW.set_position(from.name_window.left, from.name_window.top)
			
			from.name_window.hide
			from.help_window.hide
			from.item_window.show
			from.item_window.sortable = true
			from.item_window.update(true)

			
			WARNING_WINDOW.reset
			on_change
		end
		
		def on_leave(to)
			@status_phase.item_window.sortable = false
		end
		
		
		def on_select(id)
			case id
			when :sort
				Game.current_member.sort_items
				@status_phase.item_window.update(true)
				SE.equip
				Game.save(FQ_CHANGE, 'アイテム並び替え')
				on_cancel
				
			when Integer
				item = Game.current_member.items[id]
				selects = []
				item_window = @status_phase.item_window
				
				if item.effect then
					selects << SelectItem.new(:use, _('使う(U)'), SDL::Key::U)
					case $section
					when TOWN
						selects.last.disable(_("街では使えません")) unless item.effect.town_usable
					when DUNGEON
						selects.last.disable(_("キャンプ中には使えません")) unless item.effect.camp_usable
					when BATTLE
						selects.last.disable(_("戦闘中は使えません")) unless item.effect.battle_usable
					else
						raise "$section = #{$section.inspect}"
					end
					selects.last.disable(_("生きていないと使えません")) if Game.current_member.dead?
				end
				
				if item.kind_of?(Equipment) then
					if Game.current_member.equipped?(item) then
						selects << SelectItem.new(:unequip, _('外す(E)'), SDL::Key::E)
					else
						selects << SelectItem.new(:equip, _('装備(E)'), SDL::Key::E)  
						selects.last.disable(_("装備不可")) unless item.usable_by?(Game.current_member)
						
						
						
						#selects.last.disable("未識別です") if item.unidentified?
					end
				end
				selects << SelectItem.new(:trade, _('渡す(T)'), SDL::Key::T)
				selects << SelectItem.new(:trash, _('捨てる'))
				inspector = GS.party.find_member(Academian)
				if item.unidentified? && inspector then
					selects << SelectItem.new(:identify, _('識別(I)'), SDL::Key::I)
				elsif item.unidentified? && Game.debug_mode? then
					selects << SelectItem.new(:debug_identify, "識別化")
				end
				selects << SelectItem.new(:unidentify, "未識別化") if Game.debug_mode? && !(item.unidentified?)
				selects << SelectItem.new(:set_prefix, "prefix付加") if Game.debug_mode? && (item.kind_of?(Weapon) || item.kind_of?(Armor))
				
				#selects << SelectItem.new(:inspect, "#{_('識別')}(I)", SDL::Key::I) if GS.party.members.find{|x| x.kind_of?(Explorer)}
	
				item_window.update(false)
				com = Game.select(selects){|window|
					window.left = item_window.client_left + 80
					window.top = item_window.client_top + item_window.line_top(id+1) + 2
				}
				
				case com
				when :use
					catch(:cancel){
						case item.effect.target_type
						when TG_MEMBER
							WARNING_WINDOW.reset.dock_beside(PARTY_WINDOW, :right_top).show
							member_index = Game.member_select(_('だれに？'), :damaged_member_only => item.effect.damaged_member_only?)
							WARNING_WINDOW.hide
							throw(:cancel) unless member_index
							act = ItemUseAction.new(Game.current_member, [GS.party.members[member_index]], item)
						else
							act = ItemUseAction.new(Game.current_member, Game.current_member, item)
						end
						msg = act.operate
						PARTY_WINDOW.update
						Game.save(FQ_BIG_CHANGE, "#{Game.current_member.name}が#{item.name}を使用")
						message(msg)
					}
					
				when :equip
					SE.equip
					Game.current_member.equip(id)
					Game.save(FQ_CHANGE, "#{Game.current_member.name}が#{item.name}を装備")
				when :unequip
					SE.equip
					case item
					when Weapon
						Game.current_member.weapon_index = nil
					when Armor
						Game.current_member.armor_index = nil
					when Accessory
						Game.current_member.accessory_indexes.delete(id)
						Game.current_member.accessory_indexes[1] = nil
					end
					Game.save(FQ_CHANGE, "#{Game.current_member.name}が#{item.name}の装備を解除")
				when :trade
					selects = []
					GS.party.members.each_index do |i|
						to = GS.party.members[i]
						selects << SelectItem.new(i, nil)
						if to == Game.current_member then
							selects.last.disable
							info = ""
						elsif not to.getable_item?(item) then
							selects.last.disable
							info = _("持ちきれない")
						elsif not item.usable_by?(to) then
							info = "$[badcolor]空き#{10 - to.items.size}"
							selects.last.set_shortcut(i+1)
						else
							space = 10 - to.items.size
							s = '空き%{space}'
							info = n_(s, s, space).evaluate(:space => space)
							selects.last.set_shortcut(i+1)
						end
						selects.last.caption = "#{to.name}(#{i+1})"
						selects.last.right_caption = info
	
					end
					WARNING_WINDOW.show.reset(120)
					
					to_index = Game.select(selects){|window|
						window.client_width = Game.char_width * 30
						window.make_surface
						window.right = SCREEN_WIDTH - 16
						window.top = item_window.client_top + item_window.line_top(id+1) + 2
					}
					unless to_index == :cancel then
						GS.party.members[to_index].get_item(item)
						to_id = GS.members.index(GS.party.members[to_index])
						Game.current_member.lose_item(id)
						Game.save(FQ_CHANGE, "#{Game.current_member.name}が#{item.name}を#{GS.party.members[to_index].name}に渡した")
	
					end
					
				when :trash
					
					if Game.ask(_('本当に捨ててもよろしいですか？'), :default => :no) then
						Game.current_member.lose_item(id)
						Game.save(FQ_CHANGE, "#{Game.current_member.name}が#{item.name}を捨てた")
					end
					
				when :identify
					item.identify
					Game.reporter.on_item_identify(item)
					Game.save(FQ_BIG_CHANGE, "#{item.name}識別成功")
					ms = _("%{inspector}は書物を取り出し、物品をよく調べた\n\nこれは……%{item}だ！")
					message(ms.evaluate(:inspector => inspector.name, :item => item.name))
				when :debug_identify
					item.identify
				when :unidentify
					item.unidentify
				when :set_prefix
					item.set_prefix
				end
	
				
				@status_phase.update_sequence
				@status_phase.help_window.update("")
				DESCRIPTION_WINDOW.show
				item_window.update(true).show.regulate_index.warp
				@status_phase.name_window.hide
				@status_phase.help_window.hide
			end
				
			on_change
				
		end
		

		def on_change
			id = @status_phase.item_window.current_id
			case id
			when :sort
				DESCRIPTION_WINDOW.update('')
			when Integer
				self.update_item_information(Game.current_member.items[id])
			end
			#@spec_window.update(Game.current_member)
		end
		
		
		def on_cancel
			Phase.change(@status_phase)
		end
	end
	

	
	
	
	class SpellSelectPhase < Phase
		attr_reader :spell_window, :trick_window
	
		def on_enter(from)
		
			left_width = 280
			right_width = 210
		
			DESCRIPTION_WINDOW.set_position(8, 8)

			
			@spell_window = MultiColumnWindow.new.make_surface(left_width, 8)
			@spell_window.display_max = 8
			self.update_spell_window
			@spell_window.dock_beside(DESCRIPTION_WINDOW, :bottom)
			
			# 術リスト
			@trick_window = MultiColumnWindow.new.make_surface(right_width, 4)
			@trick_window.columns << ColumnItem.new(_('TRICK'), [], 140, AL_LEFT, 10)
			@trick_window.columns << ColumnItem.new(_('MP'), [], 50, AL_RIGHT)
			
			@trick_window.dock_beside(@spell_window, :right)

			# メンバー名
			NAME_WINDOW.make_surface(right_width, 1)
			NAME_WINDOW.dock_beside(@trick_window, :bottom)
			NAME_WINDOW.update(Game.current_member.name)
			

			# 術習得数
			@spell_max_window = DoubleTextWindow.new.make_surface(NAME_WINDOW.width, 1) 
			@spell_max_window.dock_beside(NAME_WINDOW, :bottom)

			# ヘルプ
			HELP_WINDOW.make_surface(NAME_WINDOW.width, 1).update([["←→", "メンバー選択"]])
			HELP_WINDOW.dock_beside(@spell_max_window, :bottom)
			
			SEAL_WINDOW.update(_('呪文習得不可'))
			SEAL_WINDOW.centering_on_window(@spell_window)

			WARNING_WINDOW.reset.dock_beside(PARTY_WINDOW, :top)
			WARNING_WINDOW.right = PARTY_WINDOW.right
			
			$windows = [PARTY_WINDOW, DESCRIPTION_WINDOW, NAME_WINDOW, @spell_max_window,
			            HELP_WINDOW, @trick_window,
			            WARNING_WINDOW, @spell_window]
			PARTY_WINDOW.update
			self.on_change
			
			@spell_window.warp
		end
		
		def on_select(id)
			if trick_selecting? then
				@trick_window.cursor_evermore_visible = true
				on_select_trick(id)
			else
				@spell_window.cursor_evermore_visible = true
				@trick_window.reset_index.show.warp
				#update_spell_window
				on_change
			end
		end
		
		def on_select_trick(id)
			trick = TRICK_DATA[id]
			actor = Game.current_member
			spell_id = @spell_window.current_id

			
			case trick.effect.target_type
			when TG_MEMBER
				index = Game.member_select(_('だれに？'))
				if index then
					action = SpellCastAction.new(Game.current_member, [GS.party.members[index]], id)
					msg = action.operate
					PARTY_WINDOW.update
					Game.save(FQ_BIG_CHANGE, "#{actor.name}が#{trick.name}を発動")
					Game.message(msg)
				end
				
			when TG_PARTY
				if Game.alive_members_select then
					action = SpellCastAction.new(Game.current_member, GS.party.alive_members, id)
					msg = action.operate
					PARTY_WINDOW.update
					Game.save(FQ_BIG_CHANGE, "#{actor.name}が#{trick.name}を発動")
					Game.message(msg)
				end
				
				
			else
				action = SpellCastAction.new(Game.current_member, GS.party.alive_members, id)
				msg = action.operate
				PARTY_WINDOW.update
				Game.save(FQ_BIG_CHANGE, "#{actor.name}が#{trick.name}を発動")
				Game.message(msg)
			end
						
			# MEMO: ここで$phaseに対して操作を行っているのは
			#       サイトビジョンを使うと、新しいSpellSelectPhaseになってしまうため
			#       （暫定処置）
			$phase.update_spell_window
			$phase.spell_window.set(spell_id)
			$phase.update_sequence
			$phase.trick_window.set(id)
			$phase.spell_window.show
			$phase.trick_window.show.warp
			
		end

		
		def on_change
			super
			update_sequence
		end
		
		def hide_unusable_trick?
			true
		end
		
		def update_sequence
			spell = @spell_window.current_id
			member = GS.party.members[$member_index]

			if member.spell_caster? then
				@spell_max_window.update([[_("習得数"), "#{member.spells.size}/#{member.spell_max}"]])
				SEAL_WINDOW.hide
				@trick_window.select_items.clear
				@trick_window.columns[1].captions.clear
				texts = ["", "", "", ""]
				if spell then
					(0..3).each do |i|
						learning = member.spell_learning[spell] || 0
						trick_symbol = SPELL_DATA[spell].trick_ids[i]
						trick = TRICK_DATA[trick_symbol]
	
						if trick && learning >= i then
							Game.on_found('trick', trick_symbol)
							item = SelectItem.new(trick_symbol, nil)
							item.caption = (trick_selecting? ? "#{trick.name}(#{KEY_TABLE[i]})" : trick.name)
							@trick_window.columns[1].captions[i] = get_mp_cost(trick_symbol)
							item.set_shortcut(KEY_TABLE[i])
							
							if hide_unusable_trick? then
								case $section
								when TOWN
									item.disable unless trick.effect.town_usable
								when DUNGEON
									item.disable unless trick.effect.camp_usable
								when BATTLE
									item.disable unless trick.effect.battle_usable
								end
							end
							
							# ブースト可能な術か？
							if Game.current_member.magic_boost? && !(trick.boostable?) then
								item.disable
							end
							
							# MPは足りているか？
							unless Game.current_member.usable_mp?(get_mp_cost(trick_symbol), @spell_window.current_id) then
								item.disable
							end
							
							
							@trick_window.select_items[i] = item
						elsif trick then
							@trick_window.select_items[i] = SelectItem.new(nil, "----------------")
						end
					end
					@trick_window.update

				
					if trick_selecting? then
						id = @trick_window.select_items[@trick_window.index].real_id
						if id then
							DESCRIPTION_WINDOW.update(TRICK_DATA[id].description)
						else
							DESCRIPTION_WINDOW.update("")
						end
					else
						DESCRIPTION_WINDOW.update(SPELL_DATA[spell].description)
					end
				else
					@trick_window.select_items.clear
					@trick_window.columns[1].captions.clear
					@trick_window.update
					
					DESCRIPTION_WINDOW.update("")
				end

			else
				@spell_max_window.update([[_("習得数"), ""]])
				SEAL_WINDOW.update(member.spell_caster? ? _("呪文未修得") : _("呪文習得不可"))
				SEAL_WINDOW.show

				@spell_window.select_items.clear
				@spell_window.columns[0].captions.clear
				@spell_window.columns[1].captions.clear
				@spell_window.update
				
				@trick_window.select_items.clear
				@trick_window.columns[1].captions.clear
				@trick_window.update
				
				DESCRIPTION_WINDOW.update("")
			end
			
		end
		
		def update_spell_window
			columns = @spell_window.columns.clear
			columns << ColumnItem.new(_("NAME"), [], 160, AL_LEFT)
			columns << ColumnItem.new(_("MP"), [], Game.char_width * 6, AL_RIGHT, 8)
			@spell_window.set_good_width
			@spell_window.make_surface
			@spell_window.select_items.clear
			member = GS.party.members[$member_index]
			if member.spell_caster? then
				member.spell_max.times do |i|
					spell = member.spells[i]
					if spell then
						name = SPELL_DATA[spell].name
						caption = (trick_selecting? ? name : "#{name}(#{KEY_TABLE[i]})")
						@spell_window.select_items << SelectItem.new(spell, caption, KEY_TABLE[i])
						columns[1].captions << sprintf("%2d/%2d", member.mp[spell], member.mp_max[spell])
					else
						@spell_window.select_items << SelectItem.new(nil, "----------------")
						columns[1].captions << ""

					end
				end
			end
			@spell_window.update.regulate_index
		end
		


		
		def trick_selecting?
			Game.current_window == @trick_window
		end

		def on_cancel			
			if self.trick_selecting? then
				on_cancel_from_trick
			else
				on_cancel_from_spell
			end
		end
		
		def on_cancel_from_trick
			@trick_window.cursor_evermore_visible = false
			@spell_window.show.warp
			update_spell_window
			self.on_change
		end
		
		def on_cancel_from_spell
			Phase.change(StatusPhase.new)
		end
		
		def get_mp_cost(trick_symbol)
			cost = TRICK_DATA[trick_symbol].mp_cost
			cost *= 2 if Game.current_member.magic_boost?
			return cost
		end
		
		def change_sequence
			NAME_WINDOW.update(Game.current_member.name)
			self.update_spell_window
			@spell_window.reset_index.update.warp
			self.on_change

		end
		

	end
	
	class StatusSpellSelectPhase < SpellSelectPhase
		include MemberChangablePhase


		def on_right_key
			unless self.trick_selecting? then
				super
			end
		end
		
		def on_left_key
			unless self.trick_selecting? then
				super
			end
		end
		def on_change_member
			change_sequence
		end


	end









	
	
	class EquipPhase < Phase
		include ItemSelectPhase
		include MemberChangablePhase
		def on_enter(from)
			super
			right_width = 200
			
			# 解説ウインドゥ
			DESCRIPTION_WINDOW.set_position(16, 16)
			
			# メインウインドゥ
			columns = MULTI_COLUMN_WINDOW.columns.clear
			select_items = MULTI_COLUMN_WINDOW.select_items.clear

			captions = [_('武器'), "", _('防具'), "", _('アクセサリー'), "", _('アクセサリー'), ""]
			columns << ColumnItem.new("", captions, 200, AL_LEFT, -180)
			columns << ColumnItem.new(s_("ColumnCaption|NAME"), [], Window.good_width('＊＊＊＊＊＊＊＊＊＊＊＊'), AL_LEFT)
			columns << ColumnItem.new(s_("ColumnCaption|MASTERY"), [], 60, AL_RIGHT)
			
			MULTI_COLUMN_WINDOW.set_good_width.make_surface(nil, 8)

	
			select_items[1] = SelectItem.new(:weapon, "", SDL::Key::W)
			select_items[3] = SelectItem.new(:armor, "", SDL::Key::A)
			select_items[5] = SelectItem.new(:accessory1, "")
			select_items[7] = SelectItem.new(:accessory2, "")
			
			MULTI_COLUMN_WINDOW.dock_beside(DESCRIPTION_WINDOW, :bottom).reset_index.warp
			
			# メンバー名
			NAME_WINDOW.make_surface(right_width, 1)
			NAME_WINDOW.dock_beside(MULTI_COLUMN_WINDOW, :right)
			
			# ヘルプ
			HELP_WINDOW.make_surface(NAME_WINDOW.width, 1).update([["←→", _('メンバー選択')]])
			HELP_WINDOW.dock_beside(NAME_WINDOW, :bottom)

			# 能力
			@spec_window = CharacterSpecWindow.new.make_surface(NAME_WINDOW.width)
			@spec_window.dock_beside(HELP_WINDOW, :bottom)
			#ITEM_DATA_WINDOW.make_surface(right_width).dock_beside(HELP_WINDOW, :bottom)


			self.update_sequence


			$windows = [PARTY_WINDOW, NAME_WINDOW, DESCRIPTION_WINDOW,
			            @spec_window, HELP_WINDOW, MULTI_COLUMN_WINDOW]
			
		end
		
		

		def on_change
			self.update_item_information(self.current_item)
			@spec_window.update(Game.current_member)
		end
		

		def current_item_index
			member = GS.party.members[$member_index]
			case MULTI_COLUMN_WINDOW.current_id
			when :weapon
				return member.weapon_index
			when :armor
				return member.armor_index
			when :accessory1
				return member.accessory_indexes[0]
			when :accessory2
				return member.accessory_indexes[1]
			end
		end

		def current_item
			return GS.party.members[$member_index].items[self.current_item_index] if self.current_item_index
		end


		
		def update_sequence
			columns = MULTI_COLUMN_WINDOW.columns
			columns[1].captions.clear
			columns[2].captions.clear
			member = GS.party.members[$member_index]
			
			columns[1].captions[1] = member.weapon.name if member.weapon
			columns[1].captions[3] = member.armor.name if member.armor
			columns[1].captions[5] = member.accessories[0].name if member.accessories[0]
			columns[1].captions[7] = member.accessories[1].name if member.accessories[1]
	
			columns[2].captions[1] = sprintf("%d%%", member.get_weapon_mastery) if member.weapon
			columns[2].captions[3] = sprintf("%d%%", member.get_armor_mastery) if member.armor
			columns[2].captions[5] = sprintf("%d%%", member.get_shield_mastery) if member.shield && member.accessories[0] == member.shield
			columns[2].captions[7] = sprintf("%d%%", member.get_shield_mastery) if member.shield && member.accessories[1] == member.shield

			self.on_change
			MULTI_COLUMN_WINDOW.update
			NAME_WINDOW.update(Game.current_member.name)
		end
		
		def on_select(id)
			Phase.change(EquipItemSelectPhase.new(id, self.current_item_index))
		end
		
		def on_change_member
			super
			self.update_sequence
			NAME_WINDOW.update(Game.current_member.name)
		end
		
		
		def on_cancel
			
			Phase.change(StatusPhase.new)
		end
	end
	
	class EquipItemSelectPhase < Phase
		include BackablePhase
		include ItemSelectPhase
	
		def initialize(equipment_type, current_item_index)
			@equipment_type = equipment_type
			@current_item_index = current_item_index
		end
	
		def on_enter(from)
			super
			left_width = 320
			right_width = 200
			
			# 解説ウインドゥ
			DESCRIPTION_WINDOW.set_position(16, 16)
			
			

			
			# メインウインドゥ
			@list_window = MULTI_COLUMN_WINDOW
			columns = @list_window.columns.clear
			select_items = @list_window.select_items.clear
			member = GS.party.members[$member_index]


			columns << ColumnItem.new(s_("ColumnCaption|NAME"), [], Window.good_width("＊＊＊＊＊＊＊＊＊＊＊＊"), AL_LEFT)
			columns << ColumnItem.new(s_("ColumnCaption|MASTERY"), [], 60, AL_RIGHT)
			
			# 「装備しない」項目作成
			select_items << SelectItem.new(-1, _("何も装備しない"))
			columns[1].captions << ""
	
			# アイテムリスト作成
			member.items.each_index do |i|
				item = member.items[i]
				
				case @equipment_type
				when :weapon
					next if not item.kind_of?(Weapon)
					select_items << SelectItem.new(i, item.name)
					columns[1].captions << sprintf("%d%%", member.weapon_mastery[item.data_id])
				when :armor
					next if not item.kind_of?(Armor)
					select_items << SelectItem.new(i, item.name)
					columns[1].captions << sprintf("%d%%", member.armor_mastery[item.data_id])
	
				when :accessory1, :accessory2
					next unless item.kind_of?(Accessory)
					
					case @equipment_type
					when :accessory1
						other_accessory = member.accessories[1]
					when :accessory2
						other_accessory = member.accessories[0]
					end
					
					if other_accessory then
						# すでにもう片方の部位で装備済みならスキップ
						next if item.eql?(other_accessory)
					end
					select_items << SelectItem.new(i, item.name)

					
					if other_accessory then
						
						# 盾二つは装備できない
						select_items.last.disable(_("盾は一つしか持てない")) if item.data.kind_of?(ShieldModel) && other_accessory.data.kind_of?(ShieldModel)
					end
					
					
					if item.data.kind_of?(ShieldModel)
						columns[1].captions << sprintf("%d%%", member.shield_mastery[item.data_id]) 
					else
						columns[1].captions << ""
					end
					
				end
				
				select_items.last.disable(_("装備不可")) unless item.usable_by?(member)

			end
			


			@list_window.make_surface(left_width, 11)
			@list_window.dock_beside(DESCRIPTION_WINDOW, :bottom)
			

			# メンバー名
			NAME_WINDOW.make_surface(right_width, 1).update
			NAME_WINDOW.dock_beside(@list_window, :right)
			

			# アイテム情報			
			ITEM_DATA_WINDOW.make_surface(right_width).dock_beside(NAME_WINDOW, :bottom)
			

			WARNING_WINDOW.reset(ITEM_DATA_WINDOW.width).dock_beside(ITEM_DATA_WINDOW, :bottom)
			
			#@change_window = DoubleTextWindow.new
			#@change_window.make_surface(right_width, 2).update
			#@change_window.inline_tag_usable = true
			#@change_window.dock_beside(ITEM_DATA_WINDOW, :under).show


			$windows = [PARTY_WINDOW, DESCRIPTION_WINDOW, NAME_WINDOW,
			            ITEM_DATA_WINDOW, WARNING_WINDOW, @list_window]
			
			@list_window.reset_index

			# 装備しているアイテムにインデックスを設定
			if @current_item_index then
				@list_window.index = @list_window.select_items.map{|x| x.id}.index(@current_item_index)
			end
			@list_window.warp

			self.on_change
		end
		
		def on_select(id)
			SE.equip
			
			# 装備品変更処理（indexが-1なら解除）
			item_index = (@list_window.current_id == -1 ? nil : @list_window.current_id)
			case @equipment_type
			when :weapon
				Game.current_member.weapon_index = item_index
			when :armor
				Game.current_member.armor_index = item_index
			when :accessory1
				Game.current_member.accessory_indexes[0] = item_index
			when :accessory2
				Game.current_member.accessory_indexes[1] = item_index
			end
			Game.save(FQ_CHANGE, "装備変更(#{(item_index ? Game.current_member.items[item_index].name : '解除')})")
			
			phase = EquipPhase.new
			Phase.change(phase)
			MULTI_COLUMN_WINDOW.set(@equipment_type).regulate_index.warp
			phase.on_change
		end
		
		def on_change
			if @list_window.current_id == -1 then
				item = nil
			else
				item = Game.current_member.items[@list_window.current_id]
			end
			
			self.update_item_information(item)

		end

		def on_cancel
			super
			MULTI_COLUMN_WINDOW.set(@equipment_type).regulate_index.warp
		end
		
	end
	





	class BuyPhase < Phase
		attr_reader :list_window
		include MemberChangablePhase
		
		def on_enter(from)
			super
			
			# ウインドゥ作成＆配置
			left_width = 320
			right_width = 200
			
			DESCRIPTION_WINDOW.set_position(8, 8)
			
			@list_window = BuyListWindow.new.make_surface(left_width, 12)
			@list_window.left = (SCREEN_WIDTH - left_width + 8 + right_width) / 2
			@list_window.reset_index
			@list_window.dock_beside(DESCRIPTION_WINDOW, :bottom)
			@list_window.display_max = 12

			
			@member_window = DoubleTextWindow.new
			@member_window.make_surface(right_width, 2)
			update_member_window
			@member_window.dock_beside(@list_window, :right)

			texts = [["←→", _("購入者選択")]]
			HELP_WINDOW.make_surface(@member_window.width, 1).update(texts)
			HELP_WINDOW.dock_beside(@member_window, :bottom)
			
			ITEM_DATA_WINDOW.make_surface(right_width).dock_beside(HELP_WINDOW, :bottom)

			$windows = [PARTY_WINDOW, DESCRIPTION_WINDOW, ITEM_DATA_WINDOW, HELP_WINDOW, @member_window, @list_window]
			
			SEAL_WINDOW.make_surface(160).update(_('購入可能なものがない'))

			# 更新
			@product_data = []
			self.update_list
			@list_window.set(0).warp
			self.on_change
			
		end
		

		
		def on_leave(to)
			@list_window = nil
		end
		
		def on_change
			if @list_window.current_product then
				ITEM_DATA_WINDOW.update(@list_window.current_product)
				DESCRIPTION_WINDOW.update(@list_window.current_product.description)
			else
				ITEM_DATA_WINDOW.update
				case @list_window.current_id
				when :share_gold
					DESCRIPTION_WINDOW.update(_("パーティーメンバー全員の所持金を山分けする"))
				when :gather_gold
					DESCRIPTION_WINDOW.update(_("すべての金貨を%{member}に集める").evaluate(:member => Game.current_member.name))
				else
					DESCRIPTION_WINDOW.update('')
				end
			end
		end
		
		def on_select(id)
			super
			return unless id
			
			case id
			when :share_gold
				GS.party.share_gold do |msg|
					self.update_list
					update_member_window
					Game.message(msg)
				end
			when :gather_gold
				GS.party.gather_gold do |msg|
					self.update_list
					update_member_window
					Game.message(msg)
				end
			else
				member = GS.party.members[$member_index]
				product = @list_window.current_product
				
				unless member.getable_item?(product) then
					message(ungetable_message(member))
					return
				end
				
				if Game.ask(confirm_message(product), :silent => true) then
					SE.coin
					member.lose_gold(product.price)
					member.get_item(product.dup)
					
					buy_sequence
	
					Game.save(FQ_BIG_CHANGE, "#{member.name}が#{product.name}を購入")
					PARTY_WINDOW.update
					
					message(buy_message)
					self.update_list
					update_member_window
					@list_window.regulate_index.warp
					on_change
				else
					SE.cancel
					@list_window.warp
				end
			end
		end
		
		def update_member_window
			@member_window.update([[Game.current_member.name], [_('所持金'), Game.current_member.gold.to_s]])
		end
		
		
		def on_change_member
			super
			self.update_list
			update_member_window
			@list_window.reset_index
			@list_window.index = 2 # 「お金を集める」「お金を山分けする」はスキップ
			@list_window.warp
			on_change
		end

		
		def select_se
			if Game.current_window == YN_WINDOW && Game.current_window.current_id == :yes then
				SE.coin
			else
				super
			end
		end
		
		def buy_sequence
		end
		
		def confirm_message(product)
			_("%{name}ですね\n金貨%{price}枚ほどいただきますが、よろしいですか？").evaluate(:name => product.name, :price => product.price)
		end
	
		def ungetable_message(member)
			_("%{member}様はこれ以上の物をお持ちになれないようです\n持ち物を整理してから、またいらしてください").evaluate(:member => member.name)
		end
		
		def buy_message
			_("お買い上げありがとうございます！\nぜひ他の品物も見ていってください")
		end

	end






	
	
	class ShopItemSelectPhase < Phase
		include MemberChangablePhase
	
		def on_enter(from)
			$member_index = 0
			DESCRIPTION_WINDOW.set_position(8, 8)
			@item_window = get_main_window
			@item_window.dock_beside(DESCRIPTION_WINDOW, :bottom)
			
			NAME_WINDOW.make_surface(200, 1).update(Game.current_member.name)
			NAME_WINDOW.dock_beside(@item_window, :right)
			

			HELP_WINDOW.make_surface(NAME_WINDOW.width, 1).update([["←→", _('メンバー選択')]])
			HELP_WINDOW.dock_beside(NAME_WINDOW, :bottom)
			
			SEAL_WINDOW.update("所持品なし")
			SEAL_WINDOW.centering_on_window(@item_window)
			
			ITEM_DATA_WINDOW.make_surface(NAME_WINDOW.width).dock_beside(HELP_WINDOW, :bottom)
			$windows = [PARTY_WINDOW, DESCRIPTION_WINDOW, ITEM_DATA_WINDOW, NAME_WINDOW, HELP_WINDOW, @item_window]
			PARTY_WINDOW.update

			@item_window.reset_index.warp
			on_change_member

		end
		
		def on_change
			id = @item_window.current_id
			if id then
				
				ITEM_DATA_WINDOW.update(Game.current_member.items[id])
				DESCRIPTION_WINDOW.update(Game.current_member.items[id].description)
			else
				ITEM_DATA_WINDOW.update(nil)
				DESCRIPTION_WINDOW.update("")
			end
		end

		
	
		
		def on_change_member
			NAME_WINDOW.update(Game.current_member.name)
			if Game.current_member.items.empty? then
				SEAL_WINDOW.show
			else
				SEAL_WINDOW.hide
				@item_window.update
				@item_window.regulate_index
			end
			on_change
		end

	end










	
	class GameConfigPhase < Phase
	
	
		def on_enter(from)
			super
			@main_window = SelectableWindow.new.make_surface(400, 9).centering
			@main_window.display_max = 9
			
			update_sequence
			@main_window.reset_index.warp
			@main_window.show
			on_change
		end
		
		
		def update_sequence
			select_items = @main_window.select_items.clear
			#select_items << SelectItem.new(:command_description_visible, "コマンドの説明", nil, (GS.game_config.command_description_visible? ? "表示する" : "表示しない"))
			select_items << SelectItem.new(:mouse_operation, _("マウス操作"), nil, (GS.game_config.mouse_operation ? _("有効") : _("無効")))
			select_items << SelectItem.new(:wall_effect, _("壁にぶつかったときの効果"), nil, GS.game_config.wall_effect_caption)
			select_items << SelectItem.new(:wizardry_like_door_open, _("扉の開け方"), nil, (GS.game_config.wizardry_like_door_open_caption))
			select_items << SelectItem.new(:dungeon_mapping, _("ダンジョン描画"), nil, GS.game_config.dungeon_mapping_caption)
			#select_items << SelectItem.new(:back_turn, _("↓キーで振り向く"), nil, (GS.game_config.back_turn ? _("可") : _("不可")))
			#select_items << SelectItem.new(:shield_mark, _("盾防御可の記号表示"), nil, (GS.game_config.shield_mark.empty? ? _("表示しない") : GS.game_config.shield_mark))
			select_items << SelectItem.new(:bgm_volume, _("BGMの音量"), nil, GS.game_config.bgm_volume_level)
			select_items << SelectItem.new(:se_volume, _("効果音の音量"), nil, GS.game_config.se_volume_level)
			select_items << SelectItem.new(:gamepad, _("ゲームパッド設定"), nil)
			select_items << SelectItem.new(:ttf, _("フォント選択"), nil)
			#select_items << SelectItem.new(:ttf_size, _("フォントサイズ選択"), nil)
			select_items << SelectItem.new(:finish, _("設定完了"))
			@main_window.update
		end
		
		def on_select(id)
			case id
			when :command_description_visible
				items = []
				items << SelectItem.new(1, _("表示する"))
				items << SelectItem.new(0, _("表示しない"))
				
				new = Game.select(items){|window|
					window.set((GS.game_config.mouse_operation ? 1 : 0))
				}
				case new
				when 1
					GS.game_config.command_description_visible = true
				when 0
					GS.game_config.command_description_visible = false
				end


			when :wizardry_like_door_open
				items = []
				items << SelectItem.new(1, GS.game_config.wizardry_like_door_open_caption(true))
				items << SelectItem.new(0, GS.game_config.wizardry_like_door_open_caption(false))
				
				new = Game.select(items){|window|
					window.set((GS.game_config.wizardry_like_door_open ? 1 : 0))
				}
				GS.game_config.wizardry_like_door_open = (new == 1 ? true : false) unless new == :cancel
			when :mouse_operation
				items = []
				items << SelectItem.new(1, _("有効"))
				items << SelectItem.new(0, _("無効"))
				
				new = Game.select(items){|window|
					window.set((GS.game_config.mouse_operation ? 1 : 0))
				}
				GS.game_config.mouse_operation = (new == 1 ? true : false) unless new == :cancel

			when :wall_effect
				items = []
				items << SelectItem.new(GameConfig::WE_NO, GS.game_config.wall_effect_caption(GameConfig::WE_NO))
				items << SelectItem.new(GameConfig::WE_SHAKE, GS.game_config.wall_effect_caption(GameConfig::WE_SHAKE))
				items << SelectItem.new(GameConfig::WE_OUCH, GS.game_config.wall_effect_caption(GameConfig::WE_OUCH))
				
				new = Game.select(items){|window|
					window.set(GS.game_config.wall_effect)
				}
				GS.game_config.wall_effect = new unless new == :cancel

			when :dungeon_mapping
				items = []
				items << SelectItem.new(GameConfig::DM_MONOCHROME, GS.game_config.dungeon_mapping_caption(GameConfig::DM_MONOCHROME))
				items << SelectItem.new(GameConfig::DM_COLORFUL, GS.game_config.dungeon_mapping_caption(GameConfig::DM_COLORFUL))
				items << SelectItem.new(GameConfig::DM_TEXTURE, GS.game_config.dungeon_mapping_caption(GameConfig::DM_TEXTURE))
				
				new = Game.select(items){|window|
					window.set(GS.game_config.dungeon_mapping)
				}
				
				if not new == :cancel and not new == GS.game_config.dungeon_mapping then
					GS.game_config.dungeon_mapping = new
					if DUNGEON_WINDOW.maked_surface? and not $section == Section::TOWN then
						Game.working(_('ダンジョン描画更新中...')){
							DUNGEON_WINDOW.make_surface
							DUNGEON_WINDOW.update
						}
					end
				end
			when :back_turn
				items = []
				items << SelectItem.new(1, "可")
				items << SelectItem.new(0, "不可")
				
				new = Game.select(items){|window|
					window.set((GS.game_config.back_turn ? 1 : 0))
				}
				GS.game_config.back_turn = (new == 1 ? true : false) unless new == :cancel
			when :shield_mark
				marks = %W([s] [S] S ])
				items = marks.map{|x| SelectItem.new(x, x)}
				items << SelectItem.new("", "表示しない")

				new = Game.select(items){|window|
					window.set(GS.game_config.shield_mark)
				}
				GS.game_config.shield_mark = new unless new == :cancel
			when :gamepad
				
				last = nil
				loop do
					assign = GS.game_config.key_assign
					ids = %w(Decide Cancel ActionMenu SystemMenu PageUp PageDown PageMoveShift LeftWalk RightWalk SideWalkShift)
					items = ids.map{|id| SelectItem.new(id, GameConfig::KEY_ASSIGN_CAPTIONS[id], nil, (assign[id] || '--'))}
					items << SelectItem.new(:assign_finish, _("設定完了"))

					assign_id = Game.select(items) do |win|
						win.make_surface(360).centering
						win.set(last) if last
					end
					
					case assign_id
					when :cancel, :assign_finish
						break
					else
						window = TextWindow.new.make_surface(400, 3).centering
						msg = _("「%{function}」の機能を割り当てる\nゲームパッドのボタンを押してください\n（ESCキーで割り当てを解除します）")
						window.update(msg.evaluate(:function => GameConfig::KEY_ASSIGN_CAPTIONS[assign_id]))
						@main_window.hide
						window.show
						Game.refresh
						wait_assign_key(assign_id)
						
						window.hide
						@main_window.show
						last = assign_id
					end
				end
			when :bgm_volume
				items = []
				(0..8).each do |level|
					items.unshift(SelectItem.new(level, level.to_s, level))
				end
				items.first.caption.concat(_(' (最大)'))
				items.last.caption.concat((' (無音)'))
				new = Game.select(items){|window|
					window.set(GS.game_config.bgm_volume_level)
				}
				unless new == :cancel then
					GS.game_config.bgm_volume_level = new
					GS.game_config.update_volume
				end
			when :se_volume
				items = []
				(0..8).each do |level|
					items.unshift(SelectItem.new(level, level.to_s, level))
				end
				items.first.caption.concat(_(' (最大)'))
				items.last.caption.concat(_(' (無音)'))
				new = Game.select(items){|window|
					window.set(GS.game_config.se_volume_level)
				}
				unless new == :cancel then
					GS.game_config.se_volume_level = new
					GS.game_config.update_volume
				end
			when :ttf
				data = []
				Game.working(_('フォント検索中...')){
					names = []
					names << 'msgothic.ttc'
					Dir.glob('res/font/*.{ttf,ttc}').sort.each do |path|
						names << File.basename(path)
					end
					
					names.each do |name|
						if (ttf_path = Game.search_font(name)) then
							data << [name, SDL::TTF.open(ttf_path, 10)]
						end
					end
				}
			
				items = data.map{|name, ttf| SelectItem.new(name, ttf.family_name)}
				re = Game.select(items, :default_id => GS.game_config.ttf_name, :display_max => 10)
				
				unless re == :cancel then
					GS.game_config.ttf_name = re
					Game.reload_ttf
					SELECT_WINDOW.update
				end
				
				data.each do |name, ttf|
					ttf.close
				end
				
			when :ttf_size
				selects = []
				[12, 14, 16].each do |size|
					selects << SelectItem.new(size, size.to_s)
				end
				
				re = Game.select(selects){|win|
					win.set(GS.game_config.ttf_size)
				}
				
				unless re == :cancel then
					GS.game_config.ttf_size = re
					Game.reload_ttf
					SELECT_WINDOW.update
				end

			when :finish
				self.finish
				return
			end
			
			update_sequence
			@main_window.show.warp
			Game.save(FQ_SMALL_CHANGE, "設定変更")
		end

		def wait_assign_key(assign_id)
			loop do
				while event = SDL::Event2.poll do
					case event
					when SDL::Event2::JoyButtonDown
						GS.game_config.key_assign[assign_id] = event.button
						SE.select
						return
					when SDL::Event2::KeyDown
						case event.sym
						when SDL::Key::ESCAPE, SDL::Key::X, SDL::Key::BACKSPACE
							GS.game_config.key_assign[assign_id] = nil
							SE.cancel
							return
						end
							
					when SDL::Event2::MouseButtonDown
						if GS.game_config.mouse_operation then
							case event.button
							when SDL::Mouse::BUTTON_RIGHT
								GS.game_config.key_assign[assign_id] = nil
								SE.cancel
								return
							end
						end
					when SDL::Event2::Quit
						Game.quit
					end

				end
			end
		end
		
		
		
		def finish
			Game.save(FQ_BIG_CHANGE, "設定変更完了")
			throw(:exit_operation_loop)
		end
		
		
		def on_cancel
			Game.save(FQ_BIG_CHANGE, "設定変更完了")
			throw(:exit_operation_loop)
		end
	end







	module OrderChangePhase
		
		def on_enter(from)
			super
			
			@old_order_window = SelectableWindow.new.make_surface(180, 6)
			@old_order_window.display_max = 6
			@new_order_window = TextWindow.new.make_surface(180, 6)
			@old_order_window.dock_beside(PARTY_WINDOW, :top)
			
			area_width = @new_order_window.width + @old_order_window.width + 8
			@old_order_window.left = (SCREEN_WIDTH - area_width) / 2
			@new_order_window.dock_beside(@old_order_window, :right)
			
			@old_members = []
			@new_members = []
			
			items = @old_order_window.select_items
			@old_members = GS.party.members.dup
			
			self.update_windows
		end
		
		def on_leave(to)
			@old_order_window = nil
			@new_order_window = nil
			@old_members = nil
			@new_members = nil
		end
		
		def update_windows
			select_items = @old_order_window.select_items

			select_items.clear
			self.rest_members.each do |member|
				i = @old_members.index(member)
				select_items << SelectItem.new(i, (member.dead? ? "$[badcolor]#{member.name}" : member.name))
			end
			@old_order_window.regulate_index
			@old_order_window.update
			
			@new_order_window.update(@new_members.map{|x| (x.dead? ? "$[badcolor]#{x.name}" : x.name)}.join("\n"))
		end
		
		def rest_members
			return @old_members - @new_members
		end
		
		def on_select(id)
			@new_members << @old_members[id]
			
			if @new_members.size == @old_members.size then
				finish
			else
				self.update_windows
			end
			
			
		end
		
		def finish
			GS.party.member_ids = @new_members.map{|x| GS.members.index(x)}
			Phase.back
		end
		
		def on_cancel
			if @new_members.empty? then
				Phase.back
			else
				@new_members.pop
				self.update_windows
			end
		end
		
	end
	


end
