# frozen_string_literal: true

class IncomingMMS
	def self.for(to, json)
		raise "Unknown encoding: #{json.inspect}" if json["encoding"] != "native"

		txt, media = extract_parts(json)

		EMPromise.all(
			txt.map { |u|
				EM::HttpRequest.new(u, tls: { verify_peer: true }).get.then(&:response)
			}
		).then do |fetched_txt|
			new(to, fetched_txt, media, clean_fake_array(json["recip"]))
		end
	end

	def self.extract_parts(json)
		clean_fake_array(json["files"])
			.grep_v(/\.smil\Z/i)
			.map { |part| "#{json['url']}&authkey=#{json['authkey']}&file=#{part}" }
			.partition { |url| url.end_with?(".txt") }
	end

	def self.clean_fake_array(str)
		# Instead of arrays we get sent comma-seperated strings
		# which sometimes contain blank elements or random whitespace
		str.to_s.split(",").map(&:strip).reject(&:empty?)
	end

	def initialize(to, txt, media, recip)
		@to = to
		@txt = txt
		@media = media
		@recip = recip
	end

	# MMS text parts are separate fetched .txt files; join with paragraph breaks
	def body_text
		@txt.empty? ? nil : @txt.join("\n\n")
	end

	def media_urls
		@media
	end

	def unproxied_to
		ProxiedJID.new(@to).unproxied
	end

	def oobs
		@media.map(&OOB.method(:new))
	end

	def addresses
		return nil if @recip.empty?

		@addresses ||= Addresses.new(
			[{ type: "to", jid: unproxied_to }] +
			@recip.map { |r| { type: "to", uri: "sms:+#{r}", delivered: true } }
		)
	end

	def to_stanza
		Blather::Stanza::Message.new(
			addresses ? unproxied_to.domain : unproxied_to,
			body_text
		).tap do |m|
			oobs.each { |oob| m << oob }
			m << addresses if addresses
		end
	end
end
