#　ログ
module DarkHall
	class Logger
		attr_reader :file
		bool_attr_reader :opened
		ROTATION_RANGE = 30 # いくつまでのLogオブジェクトを貯めておくか
		FILE_MAX = 20       # 最大保存ファイル数（超えると一つずつ削除される）
	
		def initialize(path, *excluded_log_classes)
			@path = path
			@opened = false
			@excluded_log_classes = excluded_log_classes
			@logs = []
		end
		
		def open
			@opened = true
			@file = Kernel.open(@path, 'w')
		end
		
		def close
			self.rotate
			@file.close if opened?
		end
		
		# obsolete
		def log(log_cls, *args)
			puts(log_cls.new(*args))
		end
	
		def puts(log = '')
			if opened? then
				unless log.kind_of?(Log) then
					log = UncategorizedLog.new(log)
				end
				
				@logs << log
				self.rotate if @logs.size >= ROTATION_RANGE
			end
			return self
		end
		
		alias fatal puts
		alias warn puts
		alias info puts
		alias error puts
		alias debug puts
		alias << puts
		
		def rotate
			return unless opened?
			@excluded_log_classes.each do |cls|
				@logs.delete_if{|x| x.kind_of?(cls)}
			end
			@logs.compact.each do |log|
				@file.puts(log.to_s)
			end
			@logs.clear
		end
	end
	
		

	
	
	class Log
		HR = '=' * 80
		
		def to_s
			return ""
		end
	end
	
	class StartingLog < Log
		def initialize
			@time = Time.now
		end
	
		def to_s
			timestr = sprintf("%d/%02d/%02d %02d:%02d:%02d", @time.year, @time.month,
			                  @time.day, @time.hour, @time.min, @time.sec)
			return(HR + "\n" + "　DarkHall実行ログ  " + timestr + "\n" + HR)
			
		end
	end
	
	class SystemLog < Log
	end
	
	class VideoInitializedLog < SystemLog
	
		def to_s
			buf = StringIO.new
			buf.puts("スクリーン初期化成功（#{(SETTING.use_hardware_draw? ? 'ハードウェア描画' : 'ソフトウェア描画')}）")
			buf.puts "\t画面サイズ: #{$screen.w}×#{$screen.h}"
=begin
			buf.puts "\tドライバ名: #{SDL::Screen.driver_name}"
			info = SDL::Screen.info
			buf.puts "\tビデオメモリ容量: #{info.video_mem}kb"
			buf.puts "\tbpp: #{info.bpp}"
			buf.puts "\tハードウェアサーフェス有効" if info.hw_available
			buf.puts "\tHW→HW blitアクセラレーション有効" if info.blit_hw
			buf.puts "\tSW→HW blitアクセラレーション有効" if info.blit_sw
			buf.puts "\t塗りつぶしアクセラレーション有効" if info.blit_fill
			buf.puts
=end

			return buf.string
		end
	end
	
	class MixerInitializedLog < SystemLog
		def to_s
			s = "音楽デバイス（SDL_Mixer）初期化成功\n"
			
			frequency, format, channels = SDL::Mixer.spec
			format_str = case format
			when SDL::Mixer::AUDIO_U8 then "U8"
			when SDL::Mixer::AUDIO_S8 then "S8"
			when SDL::Mixer::AUDIO_U16LSB then "U16LSB"
			when SDL::Mixer::AUDIO_S16LSB then "S16LSB"
			when SDL::Mixer::AUDIO_U16MSB then "U16MSB"
			when SDL::Mixer::AUDIO_S16MSB then "S16MSB"
			else "?"
			end

			s << sprintf("\tfrequency=%dHz format=%s channels=%d", frequency, format_str, channels)
			return s
		end
	end
	
	class JoystickInitializedLog < SystemLog
		
		def to_s
			s = "#{SDL::Joystick.num}つのゲームコントローラを認識\n"
			$joysticks.each_index do |i|
				s << "\t[#{i}] #{SDL::Joystick.index_name(i)}\n"
				s << "\t\tボタン: #{$joysticks[i].num_buttons}\n"
				s << "\t\tアナログ入力装置: #{$joysticks[i].num_axes}\n"
				s << "\t\tトラックボール: #{$joysticks[i].num_balls}\n"
			end
			return s
		end
	end
	

	
	
	# 戦闘中のログ
	class BattleLog < Log
	end
	
	# 戦闘中の行動ログ
	class BattleActionLog < BattleLog
		def to_s
		end
	end
	
	# 直接攻撃
	class AttackLog < BattleActionLog
	end
	
	# 攻撃を受けた
	class DamagedLog < BattleActionLog
	end
	
	# 武器を使用した
	class UseWeaponLog < BattleLog
		def initialize(actor, inc)
			@actor_name = actor.name
			@weapon_name = actor.weapon.name
			@inc = inc
		end
		
		def to_s
			return nil
		end
	end
	
	
	# 再配置
	class SetRoomTroopLog < Log
		def to_s
			"部屋の中の敵グループを再配置\n"
		end
	end
	
	# ランダムエンカウント
	class RandomEncountLog < Log
		def initialize(troop)
			@troop = troop.dup
		end
	
		def to_s
			
			s = "ランダムエンカウント\n"
			buf = []
			return s
			@troop.groups.each do |group|
				buf << "#{group.first.name}×#{group.size}"
			end
			s << "\t" << buf.join(', ') << "\n"
			return s
		end
	end
	
	# 未分類
	class UncategorizedLog < Log
		def initialize(body)
			@body = body
		end
		
		def to_s
			@body
		end
	end

		
	dir_path = Pathname.new("./log/")
	Dir.mkdir(dir_path) unless dir_path.exist?
	
	# 古いログを削除
	log_paths = dir_path.children.find_all{|x| x.extname == '.log'}
	log_paths.sort!
	if (over = log_paths.size - Logger::FILE_MAX + 1) >= 1 then
		over.times do |i|
			log_paths[i].delete
		end
	end
	
	now = Time.now
	time_code = sprintf("%4d%02d%02d", now.year, now.month, now.day)

	# 最新ログが同じ日付の場合、次の番号をつける
	# 日付が変わっていればまた1番からカウント
	if not log_paths.empty? and log_paths.last.basename.to_s =~ /#{time_code}_(\d+)/ then
		number = ($1.to_i + 1) % 1000
	else
		number = 1
	end
	file_path = dir_path + sprintf("%s_%03d.log", time_code, number)
	LOGGER = Logger.new(file_path.to_s)
	LOGGER.open if SETTING.use_logger?
	

	# 終了時には自動クローズ
	at_exit{
		LOGGER.close
	}

	LOGGER.log(StartingLog)
	
end






