class Async::Logger

def disable(subject)

def disable(subject)
	@subjects[subject.class] = false
end

def enable(subject)

def enable(subject)
	@subjects[subject.class] = true
end

def enabled?(subject)

def enabled?(subject)
	@subjects[subject.class] == true
end

def format(subject = nil, *arguments, &block)

def format(subject = nil, *arguments, &block)
	prefix = time_offset_prefix
	indent = " " * prefix.size
	
	buffer = Buffer.new("#{indent}| ")
	
	if subject
		format_subject(prefix, subject, output: buffer)
	end
	
	arguments.each do |argument|
		format_argument(argument, output: buffer)
	end
	
	if block_given?
		if block.arity.zero?
			format_argument(yield, output: buffer)
		else
			yield(buffer, @terminal)
		end
	end
	
	@output.write buffer.string
end

def format_argument(argument, output: @output)

def format_argument(argument, output: @output)
	if argument.is_a? Exception
		format_exception(argument, output: output)
	else
		format_value(argument, output: output)
	end
end

def format_exception(exception, prefix = nil, pwd: Dir.pwd, output: @output)

def format_exception(exception, prefix = nil, pwd: Dir.pwd, output: @output)
	output.puts " #{prefix}#{@exception_title_style}#{exception.class}#{@reset_style}: #{exception}"
	
	exception.backtrace.each_with_index do |line, index|
		path, offset, message = line.split(":")
		
		# Make the path a bit more readable
		path.gsub!(/^#{pwd}\//, "./")
		
		output.puts " #{index == 0 ? "→" : " "} #{@exception_line_style}#{path}:#{offset}#{@reset_style} #{message}"
	end
	
	if exception.cause
		format_exception(exception.cause, "Caused by ", pwd: pwd, output: output)
	end
end

def format_subject(prefix, subject, output: @output)

def format_subject(prefix, subject, output: @output)
	output.puts "#{@subject_style}#{subject}#{@reset_style}", prefix: "#{@prefix_style}#{prefix}: "
end

def format_value(value, output: @output)

def format_value(value, output: @output)
	string = value.to_s
	
	string.each_line do |line|
		output.puts "#{line}"
	end
end

def initialize(output, level: 1)

def initialize(output, level: 1)
	@output = output
	@level = level
	@start = Time.now
	
	@terminal = Terminal.new(output)
	@reset_style = @terminal.reset
	@prefix_style = @terminal.color(Terminal::Colors::CYAN)
	@subject_style = @terminal.color(nil, nil, Terminal::Attributes::BOLD)
	@exception_title_style = @terminal.color(Terminal::Colors::RED, nil, Terminal::Attributes::BOLD)
	@exception_line_style = @terminal.color(Terminal::Colors::RED)
	
	@subjects = {}
end

def level= value

def level= value
	if value.is_a? Symbol
		@level = LEVELS[value]
	else
		@level = value
	end
end

def log(level, *arguments, &block)

def log(level, *arguments, &block)
	unless level.is_a? Symbol
		level = LEVELS[level]
	end
	
	self.send(level, *arguments, &block)
end

def time_offset_prefix

def time_offset_prefix
	offset = Time.now - @start
	minutes = (offset/60).floor
	seconds = (offset - (minutes*60))
	
	if minutes > 0
		"#{minutes}m#{seconds.floor}s"
	else
		"#{seconds.round(2)}s"
	end.rjust(6)
end