# frozen_string_literal: true

class SessionManager
	class Timeout < StandardError; end

	def initialize(blather, id_msg, timeout: 10, error_if: nil)
		@blather = blather
		@sessions = {}
		@id_msg = id_msg
		@timeout = timeout
		@error_if = error_if
	end

	def promise_for(stanza, timeout: @timeout)
		id = "#{stanza.to.stripped}/#{stanza.public_send(@id_msg)}"
		@sessions.fetch(id) do
			@sessions[id] = EMPromise.new
			EM.add_timer(timeout) do
				@sessions.delete(id)&.reject(Timeout.new)
			end
			@sessions[id]
		end
	end

	def write(stanza, timeout: @timeout)
		promise = promise_for(stanza, timeout: timeout)
		@blather << stanza
		promise
	end

	def fulfill(stanza)
		id = "#{stanza.from.stripped}/#{stanza.public_send(@id_msg)}"
		if stanza.error? || @error_if&.call(stanza)
			@sessions.delete(id)&.reject(stanza)
		else
			@sessions.delete(id)&.fulfill(stanza)
		end
	end
end
