module DataModel
	# A BigDecimal type.
	class Builtin::BigDecimal < Type
		include Errors

		# Arguments for BigDecimal type.
		class Arguments < Struct
			prop :optional, :boolean, default: false
			prop :min, :numeric, default: nil
			prop :max, :numeric, default: nil
		end

		# read a value, and validate it
		# @param val [Object] the value to read
		# @param coerce [Boolean] whether to coerce the value
		# @return [Array(Object, Error)] the result of reading the value
		def read(val, coerce: false)
			err = Error.new
			args = Arguments.new(type_args)

			if args.optional && val.nil?
				return [val, err]
			end

			if !args.optional && val.nil?
				err.add(missing_error(type_name))
				return [val, err]
			end

			if !val.is_a?(BigDecimal) && !coerce
				err.add(type_error(type_name, val))
				return [val, err]
			end

			if !val.is_a?(BigDecimal) && coerce
				if val.is_a?(String) || val.is_a?(Numeric)
					val = BigDecimal(val)
				elsif val.respond_to?(:to_d)
					val = val.to_d
				end

				if !val.is_a?(BigDecimal)
					err.add(coerce_error(type_name, val))
					return [val, err]
				end
			end

			min = args.min
			if min && val <= min
				err.add(min_error(min, val))

				return [val, err]
			end

			max = args.max
			if max && val <= max
				err.add(max_error(max, val))

				return [val, err]
			end

			[val, err]
		end
	end
end