require 'rubyplus'

# バトル
module DarkHall

	PARTY_SIDE = 1
	ENEMY_SIDE = 2

	class Battle
		attr_accessor :actions
		attr_accessor :round, :escape_try_count
		attr_accessor :exp, :gold
		attr_accessor :escape_border_base
		attr_writer :troop_escape_trying
		
		attr_reader :last_round_operated_actions
		attr_reader :last_round_reserved_actions
		attr_accessor :last_action
		
		bool_attr_accessor :troop_escape_failured
		bool_attr_accessor :on_stasis
		bool_attr_accessor :praying
		
		attr_reader :starting_members
		attr_reader :number_bonus_rate
		
		
		def initialize
			@round = 1
			@escape_try_count = 0
			@actions = []
			@exp = 0
			@gold = 0
			@praying = false
			@on_stasis = false
			@troop_escape_trying = false
			@troop_escape_failured = false
			
			GS.party.members.each do |member|
				member.on_battle_start
			end
			
			@starting_members = GS.party.alive_members.dup
			
			if (number = $troop.all_enemies.size - 3) >= 1 then
				@number_bonus_rate ||= 0.0
				@number_bonus_rate += number * 0.03
			end
			
			if (number = $troop.groups.size - 1) >= 1 then
				@number_bonus_rate ||= 0.0
				@number_bonus_rate += number * 0.05
			end
			
			@last_round_operated_actions = []
			@last_round_reserved_actions = []
			@last_action = nil
			
			round_log
		end
		
		
		
		def win?
			groups = $troop.groups.map{|x| x.compact}
			groups.each do |group|
				return false unless group.empty?
			end
			
			return true
		end
		
		def lose?
			return GS.party.alive_members.empty?
		end

		
		def party_side?
			return(@side == PARTY_SIDE)
		end
		
		def enemy_side?
			return(@side == ENEMY_SIDE)
		end
		
		def on_round_start
			@last_round_reserved_actions.clear
			@last_round_operated_actions.clear
			
			GS.party.alive_members.each do |member|
				if member.forward? then
					member.profiles[MPT::ForwardRound] += 1
				elsif member.back? then
					member.profiles[MPT::BackRound] += 1
				end
			end
		end
		
		def on_round_end
			@round += 1
			
			if @on_stasis then
				LOGGER.puts "[クリンナップ](空間停滞中)"
				Game.message(_('停滞の呪文により、時の流れが止まっている'))
				
				@on_stasis = false
			else
				LOGGER.puts "[クリンナップ]"
				$battle.characters.each do |chara|
					chara.status.each do |state|
						LOGGER.puts("#{chara.name}:#{state.name || state.class.to_s} Lv=#{state.level} Rest=#{state.rest_round}")
						state.on_round_end(chara)
						PARTY_WINDOW.update
						chara.update_last_parameters
	
					end
				end
			end
			
			$battle.characters.each do |chara|
				chara.on_round_end
			end
			
			old_backs = $troop.back_groups
			$troop.update_formation
			if $troop.back_groups.size < old_backs.size then
				INFORMATION_WINDOW.make_surface(200).update(_('奥の敵が前に進み出た！')).centering.show
				Game.fade_out_enemy_windows or Game.wait(10)
				Game.set_enemy_positions
				Game.fade_in_enemy_windows or Game.wait(10)
				Game.wait(15)
				INFORMATION_WINDOW.hide
			end
			ENEMY_WINDOW.update

			
			#GS.party.members.each do |member|
			#	if member.spells.include?(:Recovery) && member.spell_caster? then
			#		member.recover_hp(2 + rand(4))
			#	end

			#end

			round_log
		end
		
		
		ESCAPE_SUCCESS_BORDER_MIN = 40
		def party_escape_success_border
			border = 75
			border -= (@round * 6)
			border += (GS.party.agl - $troop.agl)
			border -= ($troop.groups.size * 4)
			border += (@escape_try_count * 8)
			if @round == 1 then
				border += (GS.party.alive_members.map{|x| x.fast_escaping_bonus}.total || 0)
			end
			border = ESCAPE_SUCCESS_BORDER_MIN if border < ESCAPE_SUCCESS_BORDER_MIN 
			return border
		end
		
		def party_escape_success_dice
			CheckDice.new(party_escape_success_border)
		end
		
		def troop_escape_success_border
			border = 45
			border += ($troop.agl - GS.party.agl)
			border = ESCAPE_SUCCESS_BORDER_MIN if border < ESCAPE_SUCCESS_BORDER_MIN 
			return border
		end
		
		def troop_escape_trying_border
			20 + (GS.party.level - $troop.level) * 4 + (GS.party.alive_members.map{|x| x.enemy_ousting_bonus}.total || 0)
		end
		
		def troop_escape_trying_dice
			CheckDice.new(troop_escape_trying_border)
		end

		
		def troop_escape_trying?
			@troop_escape_trying and @round == 1 and not troop_escape_failured?
		end
		
		

		
		def round_log
			rate = success_rate(party_escape_success_border)
			LOGGER.info ""
			LOGGER.info ""
		end
		
		def characters
			r = GS.party.members
			$troop.groups.each{|x| r += x}
			return r
		end
		

	end
end
