module BootstrapFormExtensions
  # Extend help text to allow translations to be specified under 'helpers.help'
  def get_help_text_by_i18n_key(name)
    return if object.nil?

    HelpText.new(object, name).to_s
  end

  def required_attribute?(obj, attribute)
    RequiredAttribute.new(obj, attribute, options[:validation_context]).required?
  end

	private

	class RequiredAttribute
		def initialize(obj, attribute, context)
			@obj = obj
			@attribute = attribute
			@context = context
		end

		def required?
			return false unless obj and attribute

			presence_validator.present? && validates_in_context?
    end

    private

    attr_reader :obj, :attribute, :context

    def model_validation_context
      if presence_validator
        presence_validator.options[:on]
      end
    end

    def presence_validator
      target_validators.detect { |validator| validator.class.in? [ActiveModel::Validations::PresenceValidator, ActiveRecord::Validations::PresenceValidator] }
    end

    def target
      (obj.class == Class) ? obj : obj.class
    end

    def target_validators
      if target.respond_to? :validators_on
        target.validators_on(attribute)
      else
        []
      end
    end

    def validates_in_context?
      (model_validation_context.blank? || model_validation_context == context)
    end
  end

  class HelpText
    attr_reader :object, :name

    def initialize(object, name)
      @object = object
      @name = name
    end

    def to_s
      namespaces.map { |namespace| help_text_for(namespace) }.compact.first
    end

    private

    def help_text_for(namespace)
      underscored_scope = "#{namespace}.#{partial_scope.underscore}"
      downcased_scope = "#{namespace}.#{partial_scope.downcase}"

      help_text = I18n.t(name, scope: underscored_scope, default: '').presence
      help_text ||= if text = I18n.t(name, scope: downcased_scope, default: '').presence
                      warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
                      text
                    end

      help_text
    end

    def partial_scope
      # ActiveModel::Naming 3.X.X does not support .name; it is supported as of 4.X.X
      @partial_scope ||= object.class.model_name.respond_to?(:name) ? object.class.model_name.name : object.class.model_name
    end

    def namespaces
      %w(activerecord.help helpers.help)
    end
  end
end
