1# frozen_string_literal: true
  2
  3class Plan
  4	def self.for(plan_name)
  5		return plan_name if plan_name.is_a?(Plan)
  6
  7		plan = CONFIG[:plans].find { |p| p[:name] == plan_name }
  8		raise "No plan by that name: #{plan_name}" unless plan
  9
 10		new(plan)
 11	end
 12
 13	def self.for_registration(plan_name)
 14		plan = self.for(plan_name)
 15		raise "No registration plan by that name" unless plan.allow_register?
 16
 17		plan
 18	end
 19
 20	def initialize(plan)
 21		@plan = plan
 22	end
 23
 24	def name
 25		@plan[:name]
 26	end
 27
 28	def currency
 29		@plan[:currency]
 30	end
 31
 32	def monthly_price
 33		BigDecimal(@plan[:monthly_price]) / 10000
 34	end
 35
 36	def subaccount_discount
 37		BigDecimal(@plan[:subaccount_discount] || 0) / 10000
 38	end
 39
 40	def allow_register?
 41		!!@plan[:allow_register]
 42	end
 43
 44	def merchant_account
 45		CONFIG[:braintree][:merchant_accounts].fetch(currency) do
 46			raise "No merchant account for this currency"
 47		end
 48	end
 49
 50	def minute_limit
 51		CallingLimit.new(Limit.for("minute", @plan[:minutes]))
 52	end
 53
 54	def message_limit
 55		Limit.for("message", @plan[:messages])
 56	end
 57
 58	class Limit
 59		def self.for(unit, from_config)
 60			case from_config
 61			when :unlimited
 62				Unlimited.new(unit)
 63			else
 64				new(unit: unit, **from_config)
 65			end
 66		end
 67
 68		value_semantics do
 69			unit String
 70			included Integer
 71			price Integer
 72		end
 73
 74		def to_s
 75			"#{included} #{unit}s " \
 76			"(overage $#{'%.4f' % (price.to_d / 10000)} / #{unit})"
 77		end
 78
 79		def to_d
 80			included.to_d / 10000
 81		end
 82
 83		class Unlimited
 84			def initialize(unit)
 85				@unit = unit
 86			end
 87
 88			def to_s
 89				"unlimited #{@unit}s"
 90			end
 91		end
 92	end
 93
 94	class CallingLimit
 95		def initialize(limit)
 96			@limit = limit
 97		end
 98
 99		def to_d
100			@limit.to_d
101		end
102
103		def to_s
104			"#{'$%.4f' % to_d} of calling credit per calendar month " \
105			"(overage $#{'%.4f' % (@limit.price.to_d / 10000)} / minute)"
106		end
107	end
108end