1# frozen_string_literal: true
  2
  3require "forwardable"
  4require "ruby-bandwidth-iris"
  5Faraday.default_adapter = :em_synchrony
  6
  7class BandwidthTNOrder
  8	ORDER_DEFAULTS = {
  9		site_id: CONFIG[:bandwidth_site],
 10		peer_id: CONFIG[:bandwidth_peer]
 11	}.freeze
 12
 13	def self.get(id)
 14		EMPromise.resolve(nil).then do
 15			self.for(BandwidthIris::Order.get_order_response(
 16				# https://github.com/Bandwidth/ruby-bandwidth-iris/issues/44
 17				BandwidthIris::Client.new,
 18				id
 19			))
 20		end
 21	end
 22
 23	def self.create(
 24		tel,
 25		name: "sgx-jmp order #{tel}",
 26		reservation_id: nil,
 27		**kwargs
 28	)
 29		EMPromise.resolve(nil).then do
 30			Received.new(BandwidthIris::Order.create(
 31				name: name, **ORDER_DEFAULTS, **kwargs,
 32				existing_telephone_number_order_type: {
 33					telephone_number_list: { telephone_number: [tel.sub(/^\+?1?/, "")] }
 34				}.merge(ReservationIdList.new(reservation_id).to_h)
 35			))
 36		end
 37	end
 38
 39	def self.for(bandwidth_order)
 40		const_get(bandwidth_order.order_status.capitalize).new(bandwidth_order)
 41	rescue NameError
 42		new(bandwidth_order)
 43	end
 44
 45	extend Forwardable
 46	def_delegators :@order, :id
 47
 48	def initialize(bandwidth_order)
 49		@order = bandwidth_order
 50	end
 51
 52	def status
 53		@order[:order_status]&.downcase&.to_sym
 54	end
 55
 56	def error_description
 57		[@order[:error_list]].flatten.first&.dig(:error, :description)
 58	end
 59
 60	def poll
 61		raise "Unknown order status: #{status}"
 62	end
 63
 64	class Received < BandwidthTNOrder
 65		def status
 66			:received
 67		end
 68
 69		def poll
 70			EM.promise_timer(1).then do
 71				BandwidthTNOrder.get(id).then(&:poll)
 72			end
 73		end
 74	end
 75
 76	class Complete < BandwidthTNOrder
 77		def status
 78			:complete
 79		end
 80
 81		def tel
 82			"+1#{@order.completed_numbers[:telephone_number][:full_number]}"
 83		end
 84
 85		def poll
 86			EMPromise.resolve(self)
 87		end
 88	end
 89
 90	class Failed < BandwidthTNOrder
 91		def status
 92			:failed
 93		end
 94
 95		def poll
 96			raise "Order failed: #{id} #{error_description}"
 97		end
 98	end
 99
100	class ReservationIdList
101		def initialize(reservation_id)
102			@reservation_id = reservation_id
103		end
104
105		def to_h
106			return {} unless @reservation_id
107
108			{ reservation_id_list: { reservation_id: @reservation_id } }
109		end
110	end
111end